[njs] Fixed [[Prototype]] slot of NativeErrors.

Dmitry Volyntsev xeioex at nginx.com
Thu Oct 24 13:24:27 UTC 2019


details:   https://hg.nginx.org/njs/rev/84cb3fa5d1cc
branches:  
changeset: 1200:84cb3fa5d1cc
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Oct 24 16:17:16 2019 +0300
description:
Fixed [[Prototype]] slot of NativeErrors.

diffstat:

 src/njs_builtin.c        |   86 +++++++++-------
 src/test/njs_unit_test.c |  227 ++++++----------------------------------------
 2 files changed, 81 insertions(+), 232 deletions(-)

diffs (405 lines):

diff -r a908c2ef62ca -r 84cb3fa5d1cc src/njs_builtin.c
--- a/src/njs_builtin.c	Thu Oct 24 16:17:16 2019 +0300
+++ b/src/njs_builtin.c	Thu Oct 24 16:17:16 2019 +0300
@@ -318,6 +318,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
     for (p = njs_constructor_init; *p != NULL; p++) {
         obj = *p;
 
+        func->object.type = NJS_FUNCTION;
         func->object.shared = 0;
         func->object.extensible = 1;
         func->native = 1;
@@ -351,76 +352,76 @@ njs_prototype_function(njs_vm_t *vm, njs
 
 /*
  * Object(),
- * Object.__proto__             -> Function_Prototype,
- * Object_Prototype.__proto__   -> null,
+ * Object.__proto__             -> Function.prototype,
+ * Object.prototype.__proto__   -> null,
  *   the null value is handled by njs_object_prototype_proto(),
  *
  * Array(),
- * Array.__proto__              -> Function_Prototype,
- * Array_Prototype.__proto__    -> Object_Prototype,
+ * Array.__proto__              -> Function.prototype,
+ * Array.prototype.__proto__    -> Object.prototype,
  *
  * Boolean(),
- * Boolean.__proto__            -> Function_Prototype,
- * Boolean_Prototype.__proto__  -> Object_Prototype,
+ * Boolean.__proto__            -> Function.prototype,
+ * Boolean.prototype.__proto__  -> Object.prototype,
  *
  * Number(),
- * Number.__proto__             -> Function_Prototype,
- * Number_Prototype.__proto__   -> Object_Prototype,
+ * Number.__proto__             -> Function.prototype,
+ * Number.prototype.__proto__   -> Object.prototype,
  *
  * String(),
- * String.__proto__             -> Function_Prototype,
- * String_Prototype.__proto__   -> Object_Prototype,
+ * String.__proto__             -> Function.prototype,
+ * String.prototype.__proto__   -> Object.prototype,
  *
  * Function(),
- * Function.__proto__           -> Function_Prototype,
- * Function_Prototype.__proto__ -> Object_Prototype,
+ * Function.__proto__           -> Function.prototype,
+ * Function.prototype.__proto__ -> Object.prototype,
  *
  * RegExp(),
- * RegExp.__proto__             -> Function_Prototype,
- * RegExp_Prototype.__proto__   -> Object_Prototype,
+ * RegExp.__proto__             -> Function.prototype,
+ * RegExp.prototype.__proto__   -> Object.prototype,
  *
  * Date(),
- * Date.__proto__               -> Function_Prototype,
- * Date_Prototype.__proto__     -> Object_Prototype,
+ * Date.__proto__               -> Function.prototype,
+ * Date.prototype.__proto__     -> Object.prototype,
  *
  * Error(),
- * Error.__proto__               -> Function_Prototype,
- * Error_Prototype.__proto__     -> Object_Prototype,
+ * Error.__proto__               -> Function.prototype,
+ * Error.prototype.__proto__     -> Object.prototype,
  *
  * EvalError(),
- * EvalError.__proto__           -> Function_Prototype,
- * EvalError_Prototype.__proto__ -> Error_Prototype,
+ * EvalError.__proto__           -> Error,
+ * EvalError.prototype.__proto__ -> Error.prototype,
  *
  * InternalError(),
- * InternalError.__proto__           -> Function_Prototype,
- * InternalError_Prototype.__proto__ -> Error_Prototype,
+ * InternalError.__proto__           -> Error,
+ * InternalError.prototype.__proto__ -> Error.prototype,
  *
  * RangeError(),
- * RangeError.__proto__           -> Function_Prototype,
- * RangeError_Prototype.__proto__ -> Error_Prototype,
+ * RangeError.__proto__           -> Error,
+ * RangeError.prototype.__proto__ -> Error.prototype,
  *
  * ReferenceError(),
- * ReferenceError.__proto__           -> Function_Prototype,
- * ReferenceError_Prototype.__proto__ -> Error_Prototype,
+ * ReferenceError.__proto__           -> Error,
+ * ReferenceError.prototype.__proto__ -> Error.prototype,
  *
  * SyntaxError(),
- * SyntaxError.__proto__           -> Function_Prototype,
- * SyntaxError_Prototype.__proto__ -> Error_Prototype,
+ * SyntaxError.__proto__           -> Error,
+ * SyntaxError.prototype.__proto__ -> Error.prototype,
  *
  * TypeError(),
- * TypeError.__proto__           -> Function_Prototype,
- * TypeError_Prototype.__proto__ -> Error_Prototype,
+ * TypeError.__proto__           -> Error,
+ * TypeError.prototype.__proto__ -> Error.prototype,
  *
  * URIError(),
- * URIError.__proto__           -> Function_Prototype,
- * URIError_Prototype.__proto__ -> Error_Prototype,
+ * URIError.__proto__           -> Error,
+ * URIError.prototype.__proto__ -> Error.prototype,
  *
  * MemoryError(),
- * MemoryError.__proto__           -> Function_Prototype,
- * MemoryError_Prototype.__proto__ -> Error_Prototype,
+ * MemoryError.__proto__           -> Error,
+ * MemoryError.prototype.__proto__ -> Error.prototype,
  *
  * eval(),
- * eval.__proto__               -> Function_Prototype.
+ * eval.__proto__               -> Function.prototype.
  */
 
 njs_int_t
@@ -429,7 +430,8 @@ njs_builtin_objects_clone(njs_vm_t *vm, 
     size_t        size;
     njs_uint_t    i;
     njs_value_t   *values;
-    njs_object_t  *object_prototype, *function_prototype, *error_prototype;
+    njs_object_t  *object_prototype, *function_prototype, *error_prototype,
+                  *error_constructor;
 
     /*
      * Copy both prototypes and constructors arrays by one memcpy()
@@ -452,14 +454,22 @@ njs_builtin_objects_clone(njs_vm_t *vm, 
         vm->prototypes[i].object.__proto__ = error_prototype;
     }
 
-    function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object;
     values = vm->scopes[NJS_SCOPE_GLOBAL];
 
-    for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
+    function_prototype = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
+
+    for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_EVAL_ERROR; i++) {
         njs_set_function(&values[i], &vm->constructors[i]);
         vm->constructors[i].object.__proto__ = function_prototype;
     }
 
+    error_constructor = &vm->constructors[NJS_CONSTRUCTOR_ERROR].object;
+
+    for (i = NJS_CONSTRUCTOR_EVAL_ERROR; i < NJS_CONSTRUCTOR_MAX; i++) {
+        njs_set_function(&values[i], &vm->constructors[i]);
+        vm->constructors[i].object.__proto__ = error_constructor;
+    }
+
     vm->global_object = vm->shared->objects[0];
     vm->global_object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
     vm->global_object.shared = 0;
diff -r a908c2ef62ca -r 84cb3fa5d1cc src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Thu Oct 24 16:17:16 2019 +0300
+++ b/src/test/njs_unit_test.c	Thu Oct 24 16:17:16 2019 +0300
@@ -8661,75 +8661,9 @@ static njs_unit_test_t  njs_test[] =
               "new Error()"),
       njs_str("n: m") },
 
-    { njs_str("EvalError('e')"),
-      njs_str("EvalError: e") },
-
-    { njs_str("InternalError('e')"),
-      njs_str("InternalError: e") },
-
-    { njs_str("RangeError('e')"),
-      njs_str("RangeError: e") },
-
     { njs_str("var e = RangeError('e'); Object.preventExtensions(e);e"),
       njs_str("RangeError: e") },
 
-    { njs_str("ReferenceError('e')"),
-      njs_str("ReferenceError: e") },
-
-    { njs_str("SyntaxError('e')"),
-      njs_str("SyntaxError: e") },
-
-    { njs_str("TypeError('e')"),
-      njs_str("TypeError: e") },
-
-    { njs_str("URIError('e')"),
-      njs_str("URIError: e") },
-
-    { njs_str("MemoryError('e')"),
-      njs_str("MemoryError") },
-
-    { njs_str("EvalError('e').name + ': ' + EvalError('e').message"),
-      njs_str("EvalError: e") },
-
-    { njs_str("InternalError('e').name + ': ' + InternalError('e').message"),
-      njs_str("InternalError: e") },
-
-    { njs_str("RangeError('e').name + ': ' + RangeError('e').message"),
-      njs_str("RangeError: e") },
-
-    { njs_str("ReferenceError('e').name + ': ' + ReferenceError('e').message"),
-      njs_str("ReferenceError: e") },
-
-    { njs_str("SyntaxError('e').name + ': ' + SyntaxError('e').message"),
-      njs_str("SyntaxError: e") },
-
-    { njs_str("TypeError('e').name + ': ' + TypeError('e').message"),
-      njs_str("TypeError: e") },
-
-    { njs_str("URIError('e').name + ': ' + URIError('e').message"),
-      njs_str("URIError: e") },
-
-    { njs_str("var e = EvalError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = InternalError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = RangeError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = ReferenceError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = SyntaxError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = TypeError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
-    { njs_str("var e = URIError('e'); e.name = 'E'; e"),
-      njs_str("E: e") },
-
     /* Memory object is immutable. */
 
     { njs_str("var e = MemoryError('e'); e.name = 'E'"),
@@ -8759,134 +8693,39 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("MemoryError.prototype.name"),
       njs_str("InternalError") },
 
-    { njs_str("EvalError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("InternalError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("RangeError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("ReferenceError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("SyntaxError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("TypeError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("URIError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("MemoryError.prototype.message"),
-      njs_str("") },
-
-    { njs_str("EvalError.prototype.constructor == EvalError"),
-      njs_str("true") },
-
-    { njs_str("RangeError.prototype.constructor == RangeError"),
-      njs_str("true") },
-
-    { njs_str("ReferenceError.prototype.constructor == ReferenceError"),
-      njs_str("true") },
-
-    { njs_str("SyntaxError.prototype.constructor == SyntaxError"),
-      njs_str("true") },
-
-    { njs_str("TypeError.prototype.constructor == TypeError"),
-      njs_str("true") },
-
-    { njs_str("URIError.prototype.constructor == URIError"),
-      njs_str("true") },
-
-    { njs_str("EvalError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("RangeError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("ReferenceError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("SyntaxError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("TypeError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("URIError.prototype.hasOwnProperty('constructor')"),
-      njs_str("true") },
-
-    { njs_str("EvalError().__proto__ == EvalError.prototype"),
-      njs_str("true") },
-
-    { njs_str("RangeError().__proto__ == RangeError.prototype"),
-      njs_str("true") },
-
-    { njs_str("ReferenceError().__proto__ == ReferenceError.prototype"),
-      njs_str("true") },
-
-    { njs_str("SyntaxError().__proto__ == SyntaxError.prototype"),
-      njs_str("true") },
-
-    { njs_str("TypeError().__proto__ == TypeError.prototype"),
-      njs_str("true") },
-
-    { njs_str("URIError().__proto__ == URIError.prototype"),
-      njs_str("true") },
-
-    { njs_str("EvalError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("RangeError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("ReferenceError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("SyntaxError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("TypeError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("URIError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("MemoryError().__proto__ == MemoryError.prototype"),
-      njs_str("true") },
-
-    { njs_str("MemoryError().__proto__.__proto__ == Error.prototype"),
-      njs_str("true") },
-
-    { njs_str("typeof Error()"),
-      njs_str("object") },
-
-    { njs_str("typeof EvalError()"),
-      njs_str("object") },
-
-    { njs_str("typeof InternalError()"),
-      njs_str("object") },
-
-    { njs_str("typeof RangeError()"),
-      njs_str("object") },
-
-    { njs_str("typeof ReferenceError()"),
-      njs_str("object") },
-
-    { njs_str("typeof SyntaxError()"),
-      njs_str("object") },
-
-    { njs_str("typeof TypeError()"),
-      njs_str("object") },
-
-    { njs_str("typeof URIError()"),
-      njs_str("object") },
-
-    { njs_str("typeof MemoryError()"),
-      njs_str("object") },
+
+    /* NativeErrors. */
+
+    { njs_str(
+        "function isValidNativeError(e) {"
+        "   var inst;"
+        "   var proto = Object.getPrototypeOf(e) === Error;"
+        "   var proto2 = e.__proto__ === Error;"
+        "   var iproto = e().__proto__ === e.prototype;"
+        "   var iproto2 = e().__proto__.__proto__ === Error.prototype;"
+        "   var tpof = typeof e() === 'object';"
+        "   var ctor = e.prototype.constructor === e;"
+        "   var msg = e.prototype.message === '';"
+        "   var name = e('e').toString() === `${e.prototype.name}: e`;"
+        "   var name2 = (inst = e('e'), inst.name = 'E', inst.toString() === 'E: e');"
+        "   var name3 = (inst = e('e'), inst.name = '', inst.toString() === 'e');"
+        "   var name4 = e().toString() === `${e.prototype.name}`;"
+        "   var own_proto_ctor = e.prototype.hasOwnProperty('constructor');"
+        ""
+        "   return proto && proto2 && iproto && iproto2 "
+        "          && tpof && ctor && msg && name && name2 && name3 && name4 "
+        "          && own_proto_ctor;"
+        "};"
+        "["
+        "  EvalError,"
+        "  InternalError,"
+        "  RangeError,"
+        "  ReferenceError,"
+        "  SyntaxError,"
+        "  TypeError,"
+        "  URIError,"
+        "].every(e => isValidNativeError(e))"),
+      njs_str("true") },
 
     /* Exceptions. */
 


More information about the nginx-devel mailing list