]> git.kaiwu.me - njs.git/commitdiff
Error builtin objects.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 17 Nov 2017 15:55:07 +0000 (18:55 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 17 Nov 2017 15:55:07 +0000 (18:55 +0300)
24 files changed:
Makefile
njs/njs_array.c
njs/njs_boolean.c
njs/njs_builtin.c
njs/njs_date.c
njs/njs_error.c [new file with mode: 0644]
njs/njs_error.h [new file with mode: 0644]
njs/njs_function.c
njs/njs_generator.c
njs/njs_json.c
njs/njs_lexer_keyword.c
njs/njs_number.c
njs/njs_object.c
njs/njs_object_hash.h
njs/njs_parser.c
njs/njs_parser.h
njs/njs_regexp.c
njs/njs_string.c
njs/njs_vm.c
njs/njs_vm.h
njs/njscript.c
njs/test/njs_expect_test.exp
njs/test/njs_unit_test.c
nxt/nxt_string.h

index b1083a5eccfa57ada16e2f9d0844f2257e808c32..f73607de45e9652dc029743788aaa4c209e6d31f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ $(NXT_BUILDDIR)/libnjs.a: \
        $(NXT_BUILDDIR)/njs_function.o \
        $(NXT_BUILDDIR)/njs_regexp.o \
        $(NXT_BUILDDIR)/njs_date.o \
+       $(NXT_BUILDDIR)/njs_error.o \
        $(NXT_BUILDDIR)/njs_math.o \
        $(NXT_BUILDDIR)/njs_extern.o \
        $(NXT_BUILDDIR)/njs_variable.o \
@@ -53,6 +54,7 @@ $(NXT_BUILDDIR)/libnjs.a: \
                $(NXT_BUILDDIR)/njs_function.o \
                $(NXT_BUILDDIR)/njs_regexp.o \
                $(NXT_BUILDDIR)/njs_date.o \
+               $(NXT_BUILDDIR)/njs_error.o \
                $(NXT_BUILDDIR)/njs_math.o \
                $(NXT_BUILDDIR)/njs_extern.o \
                $(NXT_BUILDDIR)/njs_variable.o \
@@ -271,6 +273,20 @@ $(NXT_BUILDDIR)/njs_date.o: \
                -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \
                njs/njs_date.c
 
+$(NXT_BUILDDIR)/njs_error.o: \
+       $(NXT_BUILDDIR)/libnxt.a \
+       njs/njscript.h \
+       njs/njs_vm.h \
+       njs/njs_string.h \
+       njs/njs_object.h \
+       njs/njs_function.h \
+       njs/njs_error.h \
+       njs/njs_error.c \
+
+       $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_error.o $(NXT_CFLAGS) \
+               -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \
+               njs/njs_error.c
+
 $(NXT_BUILDDIR)/njs_math.o: \
        $(NXT_BUILDDIR)/libnxt.a \
        njs/njscript.h \
index 8465e2d480188e0fb4b926bd9695314d6e81bf34..8b1d559702346b348980c9919162cc3993d02c26 100644 (file)
@@ -23,6 +23,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <string.h>
 
 
@@ -248,7 +249,7 @@ njs_array_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         size = (uint32_t) num;
 
         if ((double) size != num) {
-            vm->exception = &njs_exception_range_error;
+            njs_exception_range_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
 
@@ -1713,7 +1714,7 @@ njs_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         n = njs_array_iterator_index(array, iter);
 
         if (n == NJS_ARRAY_INVALID_INDEX) {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
 
@@ -1774,7 +1775,7 @@ njs_array_iterator_args(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs)
         return NXT_OK;
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -1858,7 +1859,7 @@ njs_array_prototype_reduce_right(njs_vm_t *vm, njs_value_t *args,
                                                          unused);
 type_error:
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
index f6839af5777f93e939121a69d11a5101aa30f129..ee1cb51edb0f799d8cb977d64dde392e82e93128 100644 (file)
@@ -18,6 +18,7 @@
 #include <njs_boolean.h>
 #include <njs_object.h>
 #include <njs_function.h>
+#include <njs_error.h>
 
 
 njs_ret_t
@@ -98,7 +99,7 @@ njs_boolean_prototype_value_of(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
@@ -123,7 +124,7 @@ njs_boolean_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
index 1d36d4474aa80164c9e63a7d0474f562ed13177b..de7da438cf8da8dcd4ca90728aa9bcc9054dadb4 100644 (file)
@@ -28,6 +28,7 @@
 #include <njs_parser.h>
 #include <njs_regexp.h>
 #include <njs_date.h>
+#include <njs_error.h>
 #include <njs_math.h>
 #include <string.h>
 #include <stdio.h>
@@ -62,6 +63,15 @@ const njs_object_init_t  *njs_prototype_init[] = {
     &njs_function_prototype_init,
     &njs_regexp_prototype_init,
     &njs_date_prototype_init,
+    &njs_error_prototype_init,
+    &njs_eval_error_prototype_init,
+    &njs_internal_error_prototype_init,
+    &njs_range_error_prototype_init,
+    &njs_ref_error_prototype_init,
+    &njs_syntax_error_prototype_init,
+    &njs_type_error_prototype_init,
+    &njs_uri_error_prototype_init,
+    &njs_memory_error_prototype_init,
 };
 
 
@@ -74,6 +84,15 @@ const njs_object_init_t    *njs_constructor_init[] = {
     &njs_function_constructor_init,
     &njs_regexp_constructor_init,
     &njs_date_constructor_init,
+    &njs_error_constructor_init,
+    &njs_eval_error_constructor_init,
+    &njs_internal_error_constructor_init,
+    &njs_range_error_constructor_init,
+    &njs_ref_error_constructor_init,
+    &njs_syntax_error_constructor_init,
+    &njs_type_error_constructor_init,
+    &njs_uri_error_constructor_init,
+    &njs_memory_error_constructor_init,
 };
 
 
@@ -126,6 +145,16 @@ njs_builtin_objects_create(njs_vm_t *vm)
 
         { .date =         { .time = NAN,
                             .object = { .type = NJS_DATE } } },
+
+        { .object =       { .type = NJS_OBJECT_ERROR } },
+        { .object =       { .type = NJS_OBJECT_EVAL_ERROR } },
+        { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
+        { .object =       { .type = NJS_OBJECT_RANGE_ERROR } },
+        { .object =       { .type = NJS_OBJECT_REF_ERROR } },
+        { .object =       { .type = NJS_OBJECT_SYNTAX_ERROR } },
+        { .object =       { .type = NJS_OBJECT_TYPE_ERROR } },
+        { .object =       { .type = NJS_OBJECT_URI_ERROR } },
+        { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
     };
 
     static const njs_function_init_t  native_constructors[] = {
@@ -139,6 +168,18 @@ njs_builtin_objects_create(njs_vm_t *vm)
         { njs_regexp_constructor,
           { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_STRING_ARG } },
         { njs_date_constructor,       { 0 } },
+        { njs_error_constructor,      { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_eval_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_internal_error_constructor,
+          { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_range_error_constructor,
+          { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_ref_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_syntax_error_constructor,
+          { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_type_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_uri_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_memory_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
     };
 
     static const njs_object_init_t    *function_init[] = {
@@ -309,6 +350,42 @@ njs_builtin_objects_create(njs_vm_t *vm)
  * Date.__proto__               -> Function_Prototype,
  * Date_Prototype.__proto__     -> Object_Prototype,
  *
+ * Error(),
+ * Error.__proto__               -> Function_Prototype,
+ * Error_Prototype.__proto__     -> Object_Prototype,
+ *
+ * EvalError(),
+ * EvalError.__proto__           -> Function_Prototype,
+ * EvalError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * InternalError(),
+ * InternalError.__proto__           -> Function_Prototype,
+ * InternalError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * RangeError(),
+ * RangeError.__proto__           -> Function_Prototype,
+ * RangeError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * ReferenceError(),
+ * ReferenceError.__proto__           -> Function_Prototype,
+ * ReferenceError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * SyntaxError(),
+ * SyntaxError.__proto__           -> Function_Prototype,
+ * SyntaxError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * TypeError(),
+ * TypeError.__proto__           -> Function_Prototype,
+ * TypeError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * URIError(),
+ * URIError.__proto__           -> Function_Prototype,
+ * URIError_Prototype.__proto__ -> Error_Prototype,
+ *
+ * MemoryError(),
+ * MemoryError.__proto__           -> Function_Prototype,
+ * MemoryError_Prototype.__proto__ -> Error_Prototype,
+ *
  * eval(),
  * eval.__proto__               -> Function_Prototype.
  */
@@ -319,7 +396,7 @@ njs_builtin_objects_clone(njs_vm_t *vm)
     size_t        size;
     nxt_uint_t    i;
     njs_value_t   *values;
-    njs_object_t  *object_prototype, *function_prototype;
+    njs_object_t  *object_prototype, *function_prototype, *error_prototype;
 
     /*
      * Copy both prototypes and constructors arrays by one memcpy()
@@ -332,10 +409,16 @@ njs_builtin_objects_clone(njs_vm_t *vm)
 
     object_prototype = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
 
-    for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
+    for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_EVAL_ERROR; i++) {
         vm->prototypes[i].object.__proto__ = object_prototype;
     }
 
+    error_prototype = &vm->prototypes[NJS_PROTOTYPE_ERROR].object;
+
+    for (i = NJS_PROTOTYPE_EVAL_ERROR; i < NJS_PROTOTYPE_MAX; i++) {
+        vm->prototypes[i].object.__proto__ = error_prototype;
+    }
+
     function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object;
     values = vm->scopes[NJS_SCOPE_GLOBAL];
 
index 8a170805140f4c907b9dead6e717cfd81d8e4af3..b87b1f3a521e3f8a26dc0323231fabd9b516be17 100644 (file)
@@ -25,6 +25,7 @@
 #include <njs_object_hash.h>
 #include <njs_function.h>
 #include <njs_date.h>
+#include <njs_error.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/time.h>
@@ -1062,7 +1063,7 @@ njs_date_prototype_to_iso_string(njs_vm_t *vm, njs_value_t *args,
         return njs_string_new(vm, &vm->retval, buf, size, size);
     }
 
-    vm->exception = &njs_exception_range_error;
+    njs_exception_range_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -1910,7 +1911,7 @@ njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         }
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
diff --git a/njs/njs_error.c b/njs/njs_error.c
new file mode 100644 (file)
index 0000000..dbb560c
--- /dev/null
@@ -0,0 +1,865 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_auto_config.h>
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_string.h>
+#include <nxt_stub.h>
+#include <nxt_djb_hash.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_error.h>
+#include <njs_object.h>
+#include <njs_object_hash.h>
+#include <njs_string.h>
+#include <njs_function.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+
+static const njs_value_t  njs_error_message_string = njs_string("message");
+static const njs_value_t  njs_error_name_string = njs_string("name");
+
+
+void
+njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type,
+    const char* fmt, ...)
+{
+    size_t        size;
+    va_list       args;
+    nxt_int_t     ret;
+    njs_value_t   string, *value;
+    njs_object_t  *error;
+
+    static char  buf[256];
+
+    if (fmt != NULL) {
+        va_start(args, fmt);
+        size = vsnprintf(buf, sizeof(buf), fmt, args);
+        va_end(args);
+
+    } else {
+        size = 0;
+    }
+
+    ret = njs_string_new(vm, &string, (const u_char *) buf, size, size);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        goto memory_error;
+    }
+
+    error = njs_error_alloc(vm, type, NULL, &string);
+    if (nxt_slow_path(error == NULL)) {
+        goto memory_error;
+    }
+
+    value = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_value_t));
+    if (nxt_slow_path(value == NULL)) {
+        goto memory_error;
+    }
+
+    value->data.u.object = error;
+    value->type = type;
+    value->data.truth = 1;
+
+    vm->exception = value;
+
+    return;
+
+memory_error:
+
+    njs_exception_memory_error(vm);
+}
+
+
+nxt_noinline njs_object_t *
+njs_error_alloc(njs_vm_t *vm, njs_value_type_t type, const njs_value_t *name,
+    const njs_value_t *message)
+{
+    nxt_int_t           ret;
+    njs_object_t        *error;
+    njs_object_prop_t   *prop;
+    nxt_lvlhsh_query_t  lhq;
+
+    error = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
+    if (nxt_slow_path(error == NULL)) {
+        return NULL;
+    }
+
+    nxt_lvlhsh_init(&error->hash);
+    nxt_lvlhsh_init(&error->shared_hash);
+    error->type = type;
+    error->shared = 0;
+    error->extensible = 1;
+    error->__proto__ = &vm->prototypes[njs_error_prototype_index(type)].object;
+
+    lhq.replace = 0;
+    lhq.pool = vm->mem_cache_pool;
+
+    if (name != NULL) {
+        lhq.key = nxt_string_value("name");
+        lhq.key_hash = NJS_NAME_HASH;
+        lhq.proto = &njs_object_hash_proto;
+
+        prop = njs_object_prop_alloc(vm, &njs_error_name_string, name, 1);
+        if (nxt_slow_path(prop == NULL)) {
+            return NULL;
+        }
+
+        lhq.value = prop;
+
+        ret = nxt_lvlhsh_insert(&error->hash, &lhq);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return NULL;
+        }
+    }
+
+    if (message!= NULL) {
+        lhq.key = nxt_string_value("message");
+        lhq.key_hash = NJS_MESSAGE_HASH;
+        lhq.proto = &njs_object_hash_proto;
+
+        prop = njs_object_prop_alloc(vm, &njs_error_message_string, message, 1);
+        if (nxt_slow_path(prop == NULL)) {
+            return NULL;
+        }
+
+        prop->enumerable = 0;
+
+        lhq.value = prop;
+
+        ret = nxt_lvlhsh_insert(&error->hash, &lhq);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return NULL;
+        }
+    }
+
+    return error;
+}
+
+
+static njs_ret_t
+njs_error_create(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_value_type_t type)
+{
+    njs_object_t       *error;
+    const njs_value_t  *value;
+
+    if (nargs == 1) {
+        value = &njs_string_empty;
+
+    } else {
+        value = &args[1];
+    }
+
+    error = njs_error_alloc(vm, type, NULL, value);
+    if (nxt_slow_path(error == NULL)) {
+        njs_exception_memory_error(vm);
+        return NXT_ERROR;
+    }
+
+    vm->retval.data.u.object = error;
+    vm->retval.type = type;
+    vm->retval.data.truth = 1;
+
+    return NXT_OK;
+}
+
+
+njs_ret_t
+njs_error_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_error_constructor_properties[] =
+{
+    /* Error.name == "Error". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("Error"),
+    },
+
+    /* Error.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* Error.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_error_constructor_init = {
+    nxt_string("Error"),
+    njs_error_constructor_properties,
+    nxt_nitems(njs_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_eval_error_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_EVAL_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_eval_error_constructor_properties[] =
+{
+    /* EvalError.name == "EvalError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("EvalError"),
+    },
+
+    /* EvalError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* EvalError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_eval_error_constructor_init = {
+    nxt_string("EvalError"),
+    njs_eval_error_constructor_properties,
+    nxt_nitems(njs_eval_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_internal_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_INTERNAL_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_internal_error_constructor_properties[] =
+{
+    /* InternalError.name == "InternalError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("InternalError"),
+    },
+
+    /* InternalError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* InternalError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_internal_error_constructor_init = {
+    nxt_string("InternalError"),
+    njs_internal_error_constructor_properties,
+    nxt_nitems(njs_internal_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_range_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_RANGE_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_range_error_constructor_properties[] =
+{
+    /* RangeError.name == "RangeError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("RangeError"),
+    },
+
+    /* RangeError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* RangeError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_range_error_constructor_init = {
+    nxt_string("RangeError"),
+    njs_range_error_constructor_properties,
+    nxt_nitems(njs_range_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_ref_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_REF_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_ref_error_constructor_properties[] =
+{
+    /* ReferenceError.name == "ReferenceError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("ReferenceError"),
+    },
+
+    /* ReferenceError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* ReferenceError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_ref_error_constructor_init = {
+    nxt_string("ReferenceError"),
+    njs_ref_error_constructor_properties,
+    nxt_nitems(njs_ref_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_syntax_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_SYNTAX_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_syntax_error_constructor_properties[] =
+{
+    /* SyntaxError.name == "SyntaxError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("SyntaxError"),
+    },
+
+    /* SyntaxError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* SyntaxError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_syntax_error_constructor_init = {
+    nxt_string("SyntaxError"),
+    njs_syntax_error_constructor_properties,
+    nxt_nitems(njs_syntax_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_type_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_TYPE_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_type_error_constructor_properties[] =
+{
+    /* TypeError.name == "TypeError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("TypeError"),
+    },
+
+    /* TypeError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* TypeError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_type_error_constructor_init = {
+    nxt_string("TypeError"),
+    njs_type_error_constructor_properties,
+    nxt_nitems(njs_type_error_constructor_properties),
+};
+
+
+njs_ret_t
+njs_uri_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_error_create(vm, args, nargs, NJS_OBJECT_URI_ERROR);
+}
+
+
+static const njs_object_prop_t  njs_uri_error_constructor_properties[] =
+{
+    /* URIError.name == "URIError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("URIError"),
+    },
+
+    /* URIError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* URIError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_uri_error_constructor_init = {
+    nxt_string("URIError"),
+    njs_uri_error_constructor_properties,
+    nxt_nitems(njs_uri_error_constructor_properties),
+};
+
+
+static void
+njs_init_memory_error(njs_vm_t *vm)
+{
+    njs_value_t             *value;
+    njs_object_t            *object;
+    njs_object_prototype_t  *prototypes;
+
+    prototypes = vm->prototypes;
+    object = &vm->memory_error_object;
+
+    nxt_lvlhsh_init(&object->hash);
+    nxt_lvlhsh_init(&object->shared_hash);
+    object->__proto__ = &prototypes[NJS_PROTOTYPE_MEMORY_ERROR].object;
+    object->type = NJS_OBJECT_INTERNAL_ERROR;
+    object->shared = 1;
+
+    /*
+     * Marking it nonextensible to differentiate
+     * it from ordinary internal errors.
+     */
+    object->extensible = 0;
+
+    value = &vm->memory_error;
+
+    value->data.type = NJS_OBJECT_INTERNAL_ERROR;
+    value->data.truth = 1;
+    value->data.u.number = NAN;
+    value->data.u.object = object;
+}
+
+
+void
+njs_exception_memory_error(njs_vm_t *vm)
+{
+    njs_init_memory_error(vm);
+
+    vm->exception = &vm->memory_error;
+}
+
+
+njs_ret_t
+njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    njs_init_memory_error(vm);
+
+    vm->retval = vm->memory_error;
+
+    return NXT_OK;
+}
+
+
+static const njs_object_prop_t  njs_memory_error_constructor_properties[] =
+{
+    /* MemoryError.name == "MemoryError". */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("MemoryError"),
+    },
+
+    /* MemoryError.length == 1. */
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("length"),
+        .value = njs_value(NJS_NUMBER, 1, 1.0),
+    },
+
+    /* MemoryError.prototype. */
+    {
+        .type = NJS_NATIVE_GETTER,
+        .name = njs_string("prototype"),
+        .value = njs_native_getter(njs_object_prototype_create),
+    },
+};
+
+
+const njs_object_init_t  njs_memory_error_constructor_init = {
+    nxt_string("MemoryError"),
+    njs_memory_error_constructor_properties,
+    nxt_nitems(njs_memory_error_constructor_properties),
+};
+
+
+static njs_ret_t
+njs_error_prototype_value_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    vm->retval = args[0];
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    size_t              size;
+    u_char              *p;
+    nxt_str_t           name, message;
+    const njs_value_t   *name_value, *message_value;
+    njs_object_prop_t   *prop;
+    nxt_lvlhsh_query_t  lhq;
+
+    static const njs_value_t  default_name = njs_string("Error");
+
+    if (nargs < 1 || !njs_is_object(&args[0])) {
+        njs_exception_type_error(vm, NULL, NULL);
+        return NXT_ERROR;
+    }
+
+    lhq.key_hash = NJS_NAME_HASH;
+    lhq.key = nxt_string_value("name");
+    lhq.proto = &njs_object_hash_proto;
+
+    prop = njs_object_property(vm, args[0].data.u.object, &lhq);
+
+    if (prop != NULL) {
+        name_value = &prop->value;
+
+    } else {
+        name_value = &default_name;
+    }
+
+    njs_string_get(name_value, &name);
+
+    lhq.key_hash = NJS_MESSAGE_HASH;
+    lhq.key = nxt_string_value("message");
+
+    prop = njs_object_property(vm, args[0].data.u.object, &lhq);
+
+    if (prop != NULL) {
+        message_value = &prop->value;
+
+    } else {
+        message_value = &njs_string_empty;
+    }
+
+    njs_string_get(message_value, &message);
+
+    if (name.length == 0) {
+        vm->retval = *message_value;
+        return NJS_OK;
+    }
+
+    if (message.length == 0) {
+        vm->retval = *name_value;
+        return NJS_OK;
+    }
+
+    size = name.length + message.length + 2;
+
+    p = njs_string_alloc(vm, &vm->retval, size, size);
+
+    if (nxt_fast_path(p != NULL)) {
+        p = nxt_cpymem(p, name.start, name.length);
+        *p++ = ':';
+        *p++ = ' ';
+        memcpy(p, message.start, message.length);
+
+        return NJS_OK;
+    }
+
+    njs_exception_memory_error(vm);
+    return NJS_ERROR;
+}
+
+
+static const njs_object_prop_t  njs_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("Error"),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("message"),
+        .value = njs_string(""),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("valueOf"),
+        .value = njs_native_function(njs_error_prototype_value_of, 0, 0),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("toString"),
+        .value = njs_native_function(njs_error_prototype_to_string, 0, 0),
+    },
+};
+
+
+const njs_object_init_t  njs_error_prototype_init = {
+    nxt_string("Error"),
+    njs_error_prototype_properties,
+    nxt_nitems(njs_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_eval_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("EvalError"),
+    },
+};
+
+
+const njs_object_init_t  njs_eval_error_prototype_init = {
+    nxt_string("EvalError"),
+    njs_eval_error_prototype_properties,
+    nxt_nitems(njs_eval_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_internal_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("InternalError"),
+    },
+};
+
+
+const njs_object_init_t  njs_internal_error_prototype_init = {
+    nxt_string("InternalError"),
+    njs_internal_error_prototype_properties,
+    nxt_nitems(njs_internal_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_range_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("RangeError"),
+    },
+};
+
+
+const njs_object_init_t  njs_range_error_prototype_init = {
+    nxt_string("RangeError"),
+    njs_range_error_prototype_properties,
+    nxt_nitems(njs_range_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_ref_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("ReferenceError"),
+    },
+};
+
+
+const njs_object_init_t  njs_ref_error_prototype_init = {
+    nxt_string("ReferenceError"),
+    njs_ref_error_prototype_properties,
+    nxt_nitems(njs_ref_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_syntax_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("SyntaxError"),
+    },
+};
+
+
+const njs_object_init_t  njs_syntax_error_prototype_init = {
+    nxt_string("SyntaxError"),
+    njs_syntax_error_prototype_properties,
+    nxt_nitems(njs_syntax_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_type_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("TypeError"),
+    },
+};
+
+
+const njs_object_init_t  njs_type_error_prototype_init = {
+    nxt_string("TypeError"),
+    njs_type_error_prototype_properties,
+    nxt_nitems(njs_type_error_prototype_properties),
+};
+
+
+static const njs_object_prop_t  njs_uri_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("URIError"),
+    },
+};
+
+
+const njs_object_init_t  njs_uri_error_prototype_init = {
+    nxt_string("URIError"),
+    njs_uri_error_prototype_properties,
+    nxt_nitems(njs_uri_error_prototype_properties),
+};
+
+
+static njs_ret_t
+njs_memory_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    static const njs_value_t  name = njs_string("MemoryError");
+
+    vm->retval = name;
+
+    return NJS_OK;
+}
+
+
+static const njs_object_prop_t  njs_memory_error_prototype_properties[] =
+{
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("MemoryError"),
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("message"),
+        .value = njs_string(""),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("valueOf"),
+        .value = njs_native_function(njs_error_prototype_value_of, 0, 0),
+    },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("toString"),
+        .value = njs_native_function(njs_memory_error_prototype_to_string,
+                                     0, 0),
+    },
+};
+
+
+const njs_object_init_t  njs_memory_error_prototype_init = {
+    nxt_string("MemoryError"),
+    njs_memory_error_prototype_properties,
+    nxt_nitems(njs_memory_error_prototype_properties),
+};
diff --git a/njs/njs_error.h b/njs/njs_error.h
new file mode 100644 (file)
index 0000000..6179a8d
--- /dev/null
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_ERROR_H_INCLUDED_
+#define _NJS_ERROR_H_INCLUDED_
+
+
+#define njs_exception_error(vm, fmt, ...)                                     \
+    njs_exception_error_create(vm, NJS_OBJECT_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_eval_error(vm, fmt, ...)                                \
+    njs_exception_error_create(vm, NJS_OBJECT_EVAL_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_internal_error(vm, fmt, ...)                            \
+    njs_exception_error_create(vm, NJS_OBJECT_INTERNAL_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_range_error(vm, fmt, ...)                               \
+    njs_exception_error_create(vm, NJS_OBJECT_RANGE_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_ref_error(vm, fmt, ...)                                 \
+    njs_exception_error_create(vm, NJS_OBJECT_REF_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_syntax_error(vm, fmt, ...)                              \
+    njs_exception_error_create(vm, NJS_OBJECT_SYNTAX_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_type_error(vm, fmt, ...)                                \
+    njs_exception_error_create(vm, NJS_OBJECT_TYPE_ERROR, fmt, __VA_ARGS__)
+#define njs_exception_uri_error(vm, fmt, ...)                                 \
+    njs_exception_error_create(vm, NJS_OBJECT_URI_ERROR, fmt, __VA_ARGS__)
+
+void njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type,
+    const char* fmt, ...);
+
+void njs_exception_memory_error(njs_vm_t *vm);
+
+njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_value_type_t type,
+    const njs_value_t *name, const njs_value_t *message);
+njs_ret_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_eval_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_internal_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_range_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_ref_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_syntax_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_type_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_uri_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+
+
+extern const njs_object_init_t  njs_error_constructor_init;
+extern const njs_object_init_t  njs_eval_error_constructor_init;
+extern const njs_object_init_t  njs_internal_error_constructor_init;
+extern const njs_object_init_t  njs_range_error_constructor_init;
+extern const njs_object_init_t  njs_ref_error_constructor_init;
+extern const njs_object_init_t  njs_syntax_error_constructor_init;
+extern const njs_object_init_t  njs_type_error_constructor_init;
+extern const njs_object_init_t  njs_uri_error_constructor_init;
+extern const njs_object_init_t  njs_memory_error_constructor_init;
+
+
+extern const njs_object_init_t  njs_error_prototype_init;
+extern const njs_object_init_t  njs_eval_error_prototype_init;
+extern const njs_object_init_t  njs_internal_error_prototype_init;
+extern const njs_object_init_t  njs_range_error_prototype_init;
+extern const njs_object_init_t  njs_ref_error_prototype_init;
+extern const njs_object_init_t  njs_syntax_error_prototype_init;
+extern const njs_object_init_t  njs_type_error_prototype_init;
+extern const njs_object_init_t  njs_uri_error_prototype_init;
+extern const njs_object_init_t  njs_memory_error_prototype_init;
+
+
+#endif /* _NJS_BOOLEAN_H_INCLUDED_ */
index 4ccc93883e0110e51c37cd913e7965a90837234d..8a338295340e6aa6330094fdd1254939910cab7b 100644 (file)
@@ -20,6 +20,7 @@
 #include <njs_object.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <string.h>
 
 
@@ -230,10 +231,6 @@ njs_function_frame(njs_vm_t *vm, njs_function_t *function,
 }
 
 
-static const njs_value_t  njs_exception_stack_size_exceeded =
-    njs_long_string("RangeError: Maximum call stack size exceeded");
-
-
 nxt_noinline njs_native_frame_t *
 njs_function_frame_alloc(njs_vm_t *vm, size_t size)
 {
@@ -251,7 +248,8 @@ njs_function_frame_alloc(njs_vm_t *vm, size_t size)
         spare_size = nxt_align_size(spare_size, NJS_FRAME_SPARE_SIZE);
 
         if (vm->stack_size + spare_size > NJS_MAX_STACK_SIZE) {
-            vm->exception = &njs_exception_stack_size_exceeded;
+            njs_exception_range_error(vm, "Maximum call stack size exceeded",
+                                      NULL);
             return NULL;
         }
 
@@ -511,7 +509,7 @@ njs_function_prototype_call(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -566,7 +564,7 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
 type_error:
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -624,7 +622,7 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
index 7219f5674b17baa54bd547d2440d4ce6fa4892e2..0d98f3e0e2b795809fb1377cacb43302fb2841b3 100644 (file)
@@ -21,6 +21,7 @@
 #include <njs_function.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
+#include <njs_error.h>
 #include <string.h>
 
 
@@ -290,6 +291,15 @@ njs_generator(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
     case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
     case NJS_TOKEN_REGEXP_CONSTRUCTOR:
     case NJS_TOKEN_DATE_CONSTRUCTOR:
+    case NJS_TOKEN_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_REF_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_URI_ERROR_CONSTRUCTOR:
+    case NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR:
     case NJS_TOKEN_EXTERNAL:
         return NXT_OK;
 
@@ -331,7 +341,7 @@ njs_generator(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 
     default:
         nxt_thread_log_debug("unknown token: %d", node->token);
-        vm->exception = &njs_exception_syntax_error;
+        njs_exception_syntax_error(vm, "unknown token", NULL);
 
         return NXT_ERROR;
     }
@@ -2071,7 +2081,7 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
                          parser->code_size, code_size);
 
     if (nxt_slow_path(parser->code_size < code_size)) {
-        vm->exception = &njs_exception_internal_error;
+        njs_exception_internal_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
index e07bc18af9e16277261daf72ce60f7f8965ab095..636ab838c39732afd94ec58fa787859216baeb54 100644 (file)
@@ -23,6 +23,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -147,8 +148,6 @@ static njs_json_state_t *njs_json_push_stringify_state(njs_vm_t *vm,
     njs_json_stringify_t *stringify, njs_value_t *value);
 static njs_json_state_t *njs_json_pop_stringify_state(
     njs_json_stringify_t *stringify);
-static void njs_json_stringify_exception(njs_json_stringify_t *stringify,
-    const char* msg);
 
 static nxt_int_t njs_json_append_value(njs_json_stringify_t *stringify,
     njs_value_t *value);
@@ -188,7 +187,7 @@ njs_json_parse(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
     value = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_value_t));
     if (nxt_slow_path(value == NULL)) {
-        vm->exception = &njs_exception_memory_error;
+        njs_exception_memory_error(vm);
         return NXT_ERROR;
     }
 
@@ -256,7 +255,8 @@ njs_json_parse(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
 memory_error:
 
-    vm->exception = &njs_exception_memory_error;
+    njs_exception_memory_error(vm);
+
     return NXT_ERROR;
 }
 
@@ -342,7 +342,8 @@ njs_json_stringify(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
 memory_error:
 
-    vm->exception = &njs_exception_memory_error;
+    njs_exception_memory_error(vm);
+
     return NXT_ERROR;
 }
 
@@ -486,7 +487,7 @@ njs_json_parse_object(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
         ret = nxt_lvlhsh_insert(&object->hash, &lhq);
         if (nxt_slow_path(ret != NXT_OK)) {
-            ctx->vm->exception = &njs_exception_internal_error;
+            njs_exception_internal_error(ctx->vm, NULL, NULL);
             return NULL;
         }
 
@@ -526,7 +527,7 @@ error_end:
 
 memory_error:
 
-    ctx->vm->exception = &njs_exception_memory_error;
+    njs_exception_memory_error(ctx->vm);
 
     return NULL;
 }
@@ -546,7 +547,7 @@ njs_json_parse_array(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
     array = njs_array_alloc(ctx->vm, 0, 0);
     if (nxt_slow_path(array == NULL)) {
-        ctx->vm->exception = &njs_exception_memory_error;
+        njs_exception_memory_error(ctx->vm);
         return NULL;
     }
 
@@ -569,7 +570,7 @@ njs_json_parse_array(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
         element = nxt_mem_cache_alloc(ctx->pool, sizeof(njs_value_t));
         if (nxt_slow_path(element == NULL)) {
-            ctx->vm->exception = &njs_exception_memory_error;
+            njs_exception_memory_error(ctx->vm);
             return NULL;
         }
 
@@ -580,7 +581,7 @@ njs_json_parse_array(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
         ret = njs_array_add(ctx->vm, array, element);
         if (nxt_slow_path(ret != NXT_OK)) {
-            ctx->vm->exception = &njs_exception_internal_error;
+            njs_exception_internal_error(ctx->vm, NULL, NULL);
             return NULL;
         }
 
@@ -735,7 +736,7 @@ njs_json_parse_string(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
         start = nxt_mem_cache_alloc(ctx->pool, size);
         if (nxt_slow_path(start == NULL)) {
-            ctx->vm->exception = &njs_exception_memory_error;
+            njs_exception_memory_error(ctx->vm);;
             return NULL;
         }
 
@@ -820,7 +821,7 @@ njs_json_parse_string(njs_json_parse_ctx_t *ctx, njs_value_t *value, u_char *p)
 
     ret = njs_string_create(ctx->vm, value, start, size, length);
     if (nxt_slow_path(ret != NXT_OK)) {
-        ctx->vm->exception = &njs_exception_memory_error;
+        njs_exception_memory_error(ctx->vm);
         return NULL;
     }
 
@@ -991,7 +992,7 @@ njs_json_parse_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             }
 
             if (nxt_slow_path(ret != NXT_OK)) {
-                vm->exception = &njs_exception_internal_error;
+                njs_exception_internal_error(vm, NULL, NULL);
                 return NXT_ERROR;
             }
 
@@ -1029,14 +1030,14 @@ njs_json_parse_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             break;
 
         default:
-            vm->exception = &njs_exception_internal_error;
+            njs_exception_internal_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
 
 memory_error:
 
-    vm->exception = &njs_exception_memory_error;
+    njs_exception_memory_error(vm);
 
     return NXT_ERROR;
 }
@@ -1071,7 +1072,7 @@ njs_json_parse_continuation_apply(njs_vm_t *vm, njs_json_parse_t *parse)
         break;
 
     default:
-        vm->exception = &njs_exception_internal_error;
+        njs_exception_internal_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1131,34 +1132,14 @@ static void
 njs_json_parse_exception(njs_json_parse_ctx_t *ctx, const char* msg,
     u_char *pos)
 {
-    size_t       size;
-    ssize_t      length;
-    njs_ret_t    ret;
-    njs_value_t  *exception;
-
-    static u_char  buf[256];
-
-    exception = nxt_mem_cache_alloc(ctx->pool, sizeof(njs_value_t));
-    if (nxt_slow_path(exception == NULL)) {
-        ctx->vm->exception = &njs_exception_memory_error;
-        return;
-    }
+    ssize_t  length;
 
     length = nxt_utf8_length(ctx->start, pos - ctx->start);
     if (nxt_slow_path(length < 0)) {
         length = 0;
     }
 
-    size = snprintf((char *) buf, sizeof(buf),
-                    "SyntaxError: %s at position %zu", msg, length);
-
-    ret = njs_string_new(ctx->vm, exception, buf, size, size);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        ctx->vm->exception = &njs_exception_memory_error;
-        return;
-    }
-
-    ctx->vm->exception = exception;
+    njs_exception_syntax_error(ctx->vm, "%s at position %zu", msg, length);
 }
 
 
@@ -1450,7 +1431,8 @@ done:
 
 memory_error:
 
-    vm->exception = &njs_exception_memory_error;
+    njs_exception_memory_error(vm);
+
     return NXT_ERROR;
 }
 
@@ -1513,7 +1495,7 @@ njs_json_stringify_to_json(njs_vm_t *vm, njs_json_stringify_t* stringify,
         break;
 
     default:
-        vm->exception = &njs_exception_internal_error;
+        njs_exception_internal_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1557,7 +1539,7 @@ njs_json_stringify_replacer(njs_vm_t *vm, njs_json_stringify_t* stringify,
         break;
 
     default:
-        vm->exception = &njs_exception_internal_error;
+        njs_exception_internal_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1651,15 +1633,15 @@ njs_json_push_stringify_state(njs_vm_t *vm, njs_json_stringify_t *stringify,
     njs_json_state_t  *state;
 
     if (stringify->stack.items >= 32) {
-        njs_json_stringify_exception(stringify,
-                                     "Nested too deep or a cyclic structure");
+        njs_exception_type_error(stringify->vm,
+                                 "Nested too deep or a cyclic structure", NULL);
         return NULL;
     }
 
     state = nxt_array_add(&stringify->stack, &njs_array_mem_proto,
                            vm->mem_cache_pool);
     if (nxt_slow_path(state == NULL)) {
-        vm->exception = &njs_exception_memory_error;
+        njs_exception_memory_error(vm);
         return NULL;
     }
 
@@ -1705,33 +1687,6 @@ njs_json_pop_stringify_state(njs_json_stringify_t *stringify)
 }
 
 
-static void
-njs_json_stringify_exception(njs_json_stringify_t *stringify, const char* msg)
-{
-    size_t       size;
-    njs_ret_t    ret;
-    njs_value_t  *exception;
-
-    static u_char  buf[256];
-
-    exception = nxt_mem_cache_alloc(stringify->pool, sizeof(njs_value_t));
-    if (nxt_slow_path(exception == NULL)) {
-        stringify->vm->exception = &njs_exception_memory_error;
-        return;
-    }
-
-    size = snprintf((char *) buf, sizeof(buf), "TypeError: %s", msg);
-
-    ret = njs_string_new(stringify->vm, exception, buf, size, size);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        stringify->vm->exception = &njs_exception_memory_error;
-        return;
-    }
-
-    stringify->vm->exception = exception;
-}
-
-
 static nxt_int_t
 njs_json_append_value(njs_json_stringify_t *stringify, njs_value_t *value)
 {
@@ -1768,7 +1723,8 @@ njs_json_append_value(njs_json_stringify_t *stringify, njs_value_t *value)
         return njs_json_buf_append(stringify, "null", 4);
 
     default:
-        njs_json_stringify_exception(stringify, "Non-serializable object");
+        njs_exception_type_error(stringify->vm, "Non-serializable object",
+                                 NULL);
         return NXT_DECLINED;
     }
 }
index 9bba043aa383afad50526a81d5af8275872f11fd..3cd847630cbb91ea5bd36fc60b6fc0435799f097 100644 (file)
@@ -81,6 +81,15 @@ static const njs_keyword_t  njs_keywords[] = {
     { nxt_string("Function"),      NJS_TOKEN_FUNCTION_CONSTRUCTOR, 0 },
     { nxt_string("RegExp"),        NJS_TOKEN_REGEXP_CONSTRUCTOR, 0 },
     { nxt_string("Date"),          NJS_TOKEN_DATE_CONSTRUCTOR, 0 },
+    { nxt_string("Error"),         NJS_TOKEN_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("EvalError"),     NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("InternalError"), NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("RangeError"),    NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("ReferenceError"), NJS_TOKEN_REF_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("SyntaxError"),   NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("TypeError"),     NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("URIError"),      NJS_TOKEN_URI_ERROR_CONSTRUCTOR, 0 },
+    { nxt_string("MemoryError"),   NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR, 0 },
 
     { nxt_string("eval"),          NJS_TOKEN_EVAL, 0 },
     { nxt_string("toString"),      NJS_TOKEN_TO_STRING, 0 },
index bd731699f4dc0cc22f7acab48cc2c65af86cf282..15059a9e0f2abb2ad9fbfc01396c071c4fc4d340 100644 (file)
@@ -20,6 +20,7 @@
 #include <njs_object.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <string.h>
 #include <stdio.h>
 #include <float.h>
@@ -557,7 +558,7 @@ njs_number_prototype_value_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
@@ -583,7 +584,7 @@ njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
@@ -592,7 +593,7 @@ njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
         radix = args[1].data.u.number;
 
         if (radix < 2 || radix > 36 || radix != (int) radix) {
-            vm->exception = &njs_exception_range_error;
+            njs_exception_range_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
 
index bb6e84c2f74fd1470fe67eacad446f745ac9ad85..6e962e1e013558f7e4d6696e802adafbcfd626e5 100644 (file)
@@ -21,6 +21,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -223,7 +224,7 @@ njs_object_property(njs_vm_t *vm, njs_object_t *object, nxt_lvlhsh_query_t *lhq)
 
     } while (object != NULL);
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NULL;
 }
@@ -263,7 +264,7 @@ njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             type = njs_object_value_type(value->type);
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
 
             return NXT_ERROR;
         }
@@ -311,7 +312,7 @@ njs_object_create(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         }
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -324,13 +325,13 @@ njs_object_keys(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_array_t  *keys;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
     keys = njs_object_keys_array(vm, &args[1]);
     if (keys == NULL) {
-        vm->exception = &njs_exception_memory_error;
+        njs_exception_memory_error(vm);
         return NXT_ERROR;
     }
 
@@ -428,12 +429,12 @@ njs_object_define_property(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     nxt_int_t  ret;
 
     if (nargs < 4 || !njs_is_object(&args[1]) || !njs_is_object(&args[3])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
     if (!args[1].data.u.object->extensible) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -461,12 +462,12 @@ njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_object_prop_t  *prop;
 
     if (nargs < 3 || !njs_is_object(&args[1]) || !njs_is_object(&args[2])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
     if (!args[1].data.u.object->extensible) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -596,7 +597,7 @@ njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args,
     nxt_lvlhsh_query_t  lhq;
 
     if (nargs < 3 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -725,7 +726,7 @@ njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         return NXT_OK;
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
     return NXT_ERROR;
 }
 
@@ -740,7 +741,7 @@ njs_object_freeze(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     nxt_lvlhsh_each_t  lhe;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -779,7 +780,7 @@ njs_object_is_frozen(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     const njs_value_t  *retval;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -826,7 +827,7 @@ njs_object_seal(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     nxt_lvlhsh_each_t  lhe;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -864,7 +865,7 @@ njs_object_is_sealed(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     const njs_value_t  *retval;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -906,7 +907,7 @@ njs_object_prevent_extensions(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -925,7 +926,7 @@ njs_object_is_extensible(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     const njs_value_t  *retval;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1037,7 +1038,7 @@ njs_property_prototype_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
     }
 
     /* Memory allocation or NXT_DECLINED error. */
-    vm->exception = &njs_exception_internal_error;
+    njs_exception_internal_error(vm, NULL, NULL);
 
     return NULL;
 }
@@ -1278,7 +1279,7 @@ njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
     }
 
     /* Memory allocation or NXT_DECLINED error. */
-    vm->exception = &njs_exception_internal_error;
+    njs_exception_internal_error(vm, NULL, NULL);
 
     return NULL;
 }
@@ -1312,6 +1313,22 @@ static const njs_value_t  njs_object_function_string =
 static const njs_value_t  njs_object_regexp_string =
                                      njs_long_string("[object RegExp]");
 static const njs_value_t  njs_object_date_string = njs_string("[object Date]");
+static const njs_value_t  njs_object_error_string =
+                                     njs_string("[object Error]");
+static const njs_value_t  njs_object_eval_error_string =
+                                     njs_long_string("[object EvalError]");
+static const njs_value_t  njs_object_internal_error_string =
+                                     njs_long_string("[object InternalError]");
+static const njs_value_t  njs_object_range_error_string =
+                                     njs_long_string("[object RangeError]");
+static const njs_value_t  njs_object_ref_error_string =
+                                     njs_long_string("[object RefError]");
+static const njs_value_t  njs_object_syntax_error_string =
+                                     njs_long_string("[object SyntaxError]");
+static const njs_value_t  njs_object_type_error_string =
+                                     njs_long_string("[object TypeError]");
+static const njs_value_t  njs_object_uri_error_string =
+                                     njs_long_string("[object URIError]");
 
 
 njs_ret_t
@@ -1333,6 +1350,14 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
         &njs_string_empty,
         &njs_object_function_string,
         &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
+        &njs_string_empty,
 
         /* Objects. */
         &njs_object_object_string,
@@ -1343,6 +1368,14 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
         &njs_object_function_string,
         &njs_object_regexp_string,
         &njs_object_date_string,
+        &njs_object_error_string,
+        &njs_object_eval_error_string,
+        &njs_object_internal_error_string,
+        &njs_object_range_error_string,
+        &njs_object_ref_error_string,
+        &njs_object_syntax_error_string,
+        &njs_object_type_error_string,
+        &njs_object_uri_error_string,
     };
 
     index = args[0].type;
index ba8f6c9b6735746be3af18a2f53d4f27df51626f..eb8ec08357d1f396f0d7dfb87b4003aaf9c27ebc 100644 (file)
         'j'), 'o'), 'i'), 'n')
 
 
+#define NJS_NAME_HASH                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(NXT_DJB_HASH_INIT,                                       \
+        'n'), 'a'), 'm'), 'e')
+
+
+#define NJS_MESSAGE_HASH                                                      \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(NXT_DJB_HASH_INIT,                                       \
+        'm'), 'e'), 's'), 's'), 'a'), 'g'), 'e')
+
+
 #define NJS_PROTOTYPE_HASH                                                    \
     nxt_djb_hash_add(                                                         \
     nxt_djb_hash_add(                                                         \
index 4b99dd80a41353841188a7357e47e2c6f75a4cc7..2134dc68512cd1f602294694d467d5585b65af0b 100644 (file)
@@ -2024,6 +2024,42 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
         node->index = NJS_INDEX_DATE;
         break;
 
+    case NJS_TOKEN_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_ERROR;
+        break;
+
+    case NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_EVAL_ERROR;
+        break;
+
+    case NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_INTERNAL_ERROR;
+        break;
+
+    case NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_RANGE_ERROR;
+        break;
+
+    case NJS_TOKEN_REF_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_REF_ERROR;
+        break;
+
+    case NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_SYNTAX_ERROR;
+        break;
+
+    case NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_TYPE_ERROR;
+        break;
+
+    case NJS_TOKEN_URI_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_URI_ERROR;
+        break;
+
+    case NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR:
+        node->index = NJS_INDEX_OBJECT_MEMORY_ERROR;
+        break;
+
     case NJS_TOKEN_EVAL:
     case NJS_TOKEN_TO_STRING:
     case NJS_TOKEN_IS_NAN:
index f39fa419bf1ad8e76755bda16cd3eb002894bde5..c0990a52547f534f85144100d91cff83478835ad 100644 (file)
@@ -176,6 +176,15 @@ typedef enum {
     NJS_TOKEN_FUNCTION_CONSTRUCTOR,
     NJS_TOKEN_REGEXP_CONSTRUCTOR,
     NJS_TOKEN_DATE_CONSTRUCTOR,
+    NJS_TOKEN_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_REF_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_URI_ERROR_CONSTRUCTOR,
+    NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR,
 
 #define NJS_TOKEN_FIRST_FUNCTION   NJS_TOKEN_EVAL
 
index c64a449c66510d6c867fc402ea78d4b76133efe2..770d3693b89e0c2e9bfc14d3bcbe2c8a85128f1c 100644 (file)
@@ -25,6 +25,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
 #include <njs_regexp.h>
@@ -342,7 +343,7 @@ njs_regexp_pattern_create(njs_vm_t *vm, u_char *start, size_t length,
     if (nxt_fast_path(ret >= 0)) {
 
         if (nxt_slow_path((u_int) ret != pattern->ncaptures)) {
-            vm->exception = &njs_exception_internal_error;
+            njs_exception_internal_error(vm, NULL, NULL);
             nxt_mem_cache_free(vm->mem_cache_pool, pattern);
             return NULL;
         }
@@ -578,7 +579,7 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
         return njs_regexp_string_create(vm, &vm->retval, source, size, length);
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -596,7 +597,7 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_regexp_pattern_t  *pattern;
 
     if (!njs_is_regexp(&args[0])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -646,7 +647,7 @@ njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     nxt_regex_match_data_t  *match_data;
 
     if (!njs_is_regexp(&args[0])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
index 040c38877171a6866dd2f436b959831f72cf7afa..915737386b3388db2fff5b93aae490d95cab6022 100644 (file)
@@ -26,6 +26,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
 #include <njs_regexp.h>
@@ -551,7 +552,7 @@ njs_string_prototype_value_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
@@ -576,7 +577,7 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_string_prop_t  string;
 
     if (njs_is_null_or_void(&args[0])) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1166,7 +1167,7 @@ njs_string_from_char_code(njs_vm_t *vm, njs_value_t *args,
 
 range_error:
 
-    vm->exception = &njs_exception_range_error;
+    njs_exception_range_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -1833,7 +1834,7 @@ njs_string_prototype_repeat(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         n = args[1].data.u.number;
 
         if (nxt_slow_path(n < 0 || n >= max)) {
-            vm->exception = &njs_exception_range_error;
+            njs_exception_range_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
@@ -2537,7 +2538,7 @@ njs_string_replace_regexp_continuation(njs_vm_t *vm, njs_value_t *args,
 
     nxt_regex_match_data_free(r->match_data, vm->regex_context);
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -2649,7 +2650,7 @@ njs_string_replace_search_continuation(njs_vm_t *vm, njs_value_t *args,
         return njs_string_replace_join(vm, r);
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -3600,7 +3601,7 @@ njs_string_decode(njs_vm_t *vm, njs_value_t *value, const uint32_t *reserve)
 
 uri_error:
 
-    vm->exception = &njs_exception_uri_error;
+    njs_exception_uri_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
index 7bc45db0749f6147e480f1c82c04ebdd9f2cbe5c..5fee478d82fb791028e8971cbc7cf408c5bc41d3 100644 (file)
@@ -24,6 +24,7 @@
 #include <njs_object_hash.h>
 #include <njs_array.h>
 #include <njs_function.h>
+#include <njs_error.h>
 #include <njs_extern.h>
 #include <njs_variable.h>
 #include <njs_parser.h>
@@ -144,13 +145,7 @@ const njs_value_t  njs_string_string =      njs_string("string");
 const njs_value_t  njs_string_object =      njs_string("object");
 const njs_value_t  njs_string_function =    njs_string("function");
 
-const njs_value_t  njs_exception_syntax_error =    njs_string("SyntaxError");
-const njs_value_t  njs_exception_reference_error = njs_string("ReferenceError");
-const njs_value_t  njs_exception_type_error =      njs_string("TypeError");
-const njs_value_t  njs_exception_range_error =     njs_string("RangeError");
-const njs_value_t  njs_exception_uri_error =       njs_string("URIError");
-const njs_value_t  njs_exception_memory_error =    njs_string("MemoryError");
-const njs_value_t  njs_exception_internal_error =  njs_string("InternalError");
+const njs_value_t  njs_string_memory_error = njs_string("MemoryError");
 
 
 /*
@@ -679,7 +674,7 @@ njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object,
     njs_vmcode_prop_set_t  *code;
 
     if (njs_is_primitive(object)) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -799,7 +794,7 @@ njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *object, njs_value_t *property)
 
     case NJS_PRIMITIVE_VALUE:
     case NJS_STRING_VALUE:
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
 
         return NXT_ERROR;
 
@@ -1013,6 +1008,14 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
     case NJS_OBJECT_STRING:
     case NJS_REGEXP:
     case NJS_DATE:
+    case NJS_OBJECT_ERROR:
+    case NJS_OBJECT_EVAL_ERROR:
+    case NJS_OBJECT_INTERNAL_ERROR:
+    case NJS_OBJECT_RANGE_ERROR:
+    case NJS_OBJECT_REF_ERROR:
+    case NJS_OBJECT_SYNTAX_ERROR:
+    case NJS_OBJECT_TYPE_ERROR:
+    case NJS_OBJECT_URI_ERROR:
         obj = object->data.u.object;
         break;
 
@@ -1036,7 +1039,7 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
         break;
 
     default:  /* NJS_VOID, NJS_NULL. */
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1319,7 +1322,7 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
     nxt_lvlhsh_query_t  lhq;
 
     if (!njs_is_function(constructor)) {
-        vm->exception = &njs_exception_type_error;
+        njs_exception_type_error(vm, NULL, NULL);
         return NXT_ERROR;
     }
 
@@ -1476,6 +1479,14 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
         &njs_string_void,
         &njs_string_void,
         &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
+        &njs_string_void,
 
         &njs_string_object,
         &njs_string_object,
@@ -1485,6 +1496,14 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
         &njs_string_function,
         &njs_string_object,
         &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
+        &njs_string_object,
     };
 
     /* A zero index means non-declared variable. */
@@ -2226,7 +2245,7 @@ njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
         }
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -2334,7 +2353,7 @@ njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
 
 type_error:
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -2555,7 +2574,7 @@ trap:
 
 type_error:
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
@@ -3154,7 +3173,7 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
         if (!njs_is_primitive(retval)) {
 
             for ( ;; ) {
-                vm->exception = &njs_exception_type_error;
+                njs_exception_type_error(vm, NULL, NULL);
                 ret = NXT_ERROR;
 
                 if (njs_is_object(value) && vm->top_frame->trap_tries < 2) {
@@ -3260,6 +3279,14 @@ njs_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src)
 
     if (nxt_fast_path(src != NULL)) {
 
+        if (nxt_slow_path(src->type == NJS_OBJECT_INTERNAL_ERROR)) {
+
+            /* MemoryError is a nonextensible internal error. */
+            if (!src->data.u.object->extensible) {
+                src = &njs_string_memory_error;
+            }
+        }
+
         value = *src;
 
         if (nxt_slow_path(!njs_is_primitive(&value))) {
index 79a6f122cae288dff524415339daa99aa2b4f8b9..1fcd18c12e58f425eef0e35d4824e9da575e6eaf 100644 (file)
  */
 
 typedef enum {
-    NJS_NULL            = 0x00,
-    NJS_VOID            = 0x01,
+    NJS_NULL                  = 0x00,
+    NJS_VOID                  = 0x01,
 
     /* The order of the above type is used in njs_is_null_or_void(). */
 
-    NJS_BOOLEAN         = 0x02,
+    NJS_BOOLEAN               = 0x02,
     /*
      * The order of the above type is used in njs_is_null_or_void_or_boolean().
      */
-    NJS_NUMBER          = 0x03,
+    NJS_NUMBER                = 0x03,
     /*
      * The order of the above type is used in njs_is_numeric().
      * Booleans, null and void values can be used in mathematical operations:
@@ -71,14 +71,14 @@ typedef enum {
      *   a numeric value of the null and false values is zero,
      *   a numeric value of the void value is NaN.
      */
-    NJS_STRING          = 0x04,
+    NJS_STRING                = 0x04,
 
     /* The order of the above type is used in njs_is_primitive(). */
 
-    /* Reserved           0x05, */
+    /* Reserved                 0x05, */
 
     /* The type is external code. */
-    NJS_EXTERNAL        = 0x06,
+    NJS_EXTERNAL              = 0x06,
 
     /*
      * The invalid value type is used:
@@ -86,23 +86,31 @@ typedef enum {
      *   to detect non-declared explicitly or implicitly variables,
      *   for native property getters.
      */
-    NJS_INVALID         = 0x07,
+    NJS_INVALID               = 0x07,
 
     /*
-     * The object types have the third bit set.  It is used in njs_is_object().
+     * The object types have the fourth bit set.  It is used in njs_is_object().
      * NJS_OBJECT_BOOLEAN, NJS_OBJECT_NUMBER, and NJS_OBJECT_STRING must be
      * in the same order as NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING.  It is
      * used in njs_primitive_prototype_index().  The order of object types
      * is used in vm->prototypes and vm->constructors arrays.
      */
-    NJS_OBJECT          = 0x08,
-    NJS_ARRAY           = 0x09,
-    NJS_OBJECT_BOOLEAN  = 0x0a,
-    NJS_OBJECT_NUMBER   = 0x0b,
-    NJS_OBJECT_STRING   = 0x0c,
-    NJS_FUNCTION        = 0x0d,
-    NJS_REGEXP          = 0x0e,
-    NJS_DATE            = 0x0f,
+    NJS_OBJECT                = 0x10,
+    NJS_ARRAY                 = 0x11,
+    NJS_OBJECT_BOOLEAN        = 0x12,
+    NJS_OBJECT_NUMBER         = 0x13,
+    NJS_OBJECT_STRING         = 0x14,
+    NJS_FUNCTION              = 0x15,
+    NJS_REGEXP                = 0x16,
+    NJS_DATE                  = 0x17,
+    NJS_OBJECT_ERROR          = 0x18,
+    NJS_OBJECT_EVAL_ERROR     = 0x19,
+    NJS_OBJECT_INTERNAL_ERROR = 0x1a,
+    NJS_OBJECT_RANGE_ERROR    = 0x1b,
+    NJS_OBJECT_REF_ERROR      = 0x1c,
+    NJS_OBJECT_SYNTAX_ERROR   = 0x1d,
+    NJS_OBJECT_TYPE_ERROR     = 0x1e,
+    NJS_OBJECT_URI_ERROR      = 0x1f,
 } njs_value_type_t;
 
 
@@ -145,7 +153,7 @@ union njs_value_s {
      * the maximum size of short string to 13.
      */
     struct {
-        njs_value_type_t              type:8;  /* 4 bits */
+        njs_value_type_t              type:8;  /* 5 bits */
         /*
          * The truth field is set during value assignment and then can be
          * quickly tested by logical and conditional operations regardless
@@ -181,7 +189,7 @@ union njs_value_s {
     } data;
 
     struct {
-        njs_value_type_t              type:8;  /* 4 bits */
+        njs_value_type_t              type:8;  /* 5 bits */
 
 #define NJS_STRING_SHORT              14
 #define NJS_STRING_LONG               15
@@ -192,7 +200,7 @@ union njs_value_s {
         u_char                        start[NJS_STRING_SHORT];
     } short_string;
 
-    njs_value_type_t                  type:8;  /* 4 bits */
+    njs_value_type_t                  type:8;  /* 5 bits */
 };
 
 
@@ -402,6 +410,10 @@ typedef njs_ret_t (*njs_vmcode_operation_t)(njs_vm_t *vm, njs_value_t *value1,
 #define njs_is_string(value)                                                  \
     ((value)->type == NJS_STRING)
 
+#define njs_is_error(value)                                                   \
+    ((value)->type >= NJS_OBJECT_ERROR                                        \
+     && (value)->type <= NJS_OBJECT_URI_ERROR)
+
 
 /*
  * The truth field coincides with short_string.size and short_string.length
@@ -760,7 +772,6 @@ typedef enum {
 #define njs_is_callee_argument_index(index)                                   \
     (((index) & NJS_SCOPE_CALLEE_ARGUMENTS) == NJS_SCOPE_CALLEE_ARGUMENTS)
 
-
 enum njs_prototypes_e {
     NJS_PROTOTYPE_OBJECT = 0,
     NJS_PROTOTYPE_ARRAY,
@@ -770,27 +781,50 @@ enum njs_prototypes_e {
     NJS_PROTOTYPE_FUNCTION,
     NJS_PROTOTYPE_REGEXP,
     NJS_PROTOTYPE_DATE,
-#define NJS_PROTOTYPE_MAX      (NJS_PROTOTYPE_DATE + 1)
+    NJS_PROTOTYPE_ERROR,
+    NJS_PROTOTYPE_EVAL_ERROR,
+    NJS_PROTOTYPE_INTERNAL_ERROR,
+    NJS_PROTOTYPE_RANGE_ERROR,
+    NJS_PROTOTYPE_REF_ERROR,
+    NJS_PROTOTYPE_SYNTAX_ERROR,
+    NJS_PROTOTYPE_TYPE_ERROR,
+    NJS_PROTOTYPE_URI_ERROR,
+    NJS_PROTOTYPE_MEMORY_ERROR,
+#define NJS_PROTOTYPE_MAX      (NJS_PROTOTYPE_MEMORY_ERROR + 1)
 };
 
 
 #define njs_primitive_prototype_index(type)                                   \
     (NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
 
+
+#define njs_error_prototype_index(type)                                       \
+    (NJS_PROTOTYPE_ERROR + ((type) - NJS_OBJECT_ERROR))
+
+
 #define njs_prototype_type(index)                                             \
     (index + NJS_OBJECT)
 
 
 enum njs_constructor_e {
-    NJS_CONSTRUCTOR_OBJECT =   NJS_PROTOTYPE_OBJECT,
-    NJS_CONSTRUCTOR_ARRAY =    NJS_PROTOTYPE_ARRAY,
-    NJS_CONSTRUCTOR_BOOLEAN =  NJS_PROTOTYPE_BOOLEAN,
-    NJS_CONSTRUCTOR_NUMBER =   NJS_PROTOTYPE_NUMBER,
-    NJS_CONSTRUCTOR_STRING =   NJS_PROTOTYPE_STRING,
-    NJS_CONSTRUCTOR_FUNCTION = NJS_PROTOTYPE_FUNCTION,
-    NJS_CONSTRUCTOR_REGEXP =   NJS_PROTOTYPE_REGEXP,
-    NJS_CONSTRUCTOR_DATE =     NJS_PROTOTYPE_DATE,
-#define NJS_CONSTRUCTOR_MAX    (NJS_CONSTRUCTOR_DATE + 1)
+    NJS_CONSTRUCTOR_OBJECT =         NJS_PROTOTYPE_OBJECT,
+    NJS_CONSTRUCTOR_ARRAY =          NJS_PROTOTYPE_ARRAY,
+    NJS_CONSTRUCTOR_BOOLEAN =        NJS_PROTOTYPE_BOOLEAN,
+    NJS_CONSTRUCTOR_NUMBER =         NJS_PROTOTYPE_NUMBER,
+    NJS_CONSTRUCTOR_STRING =         NJS_PROTOTYPE_STRING,
+    NJS_CONSTRUCTOR_FUNCTION =       NJS_PROTOTYPE_FUNCTION,
+    NJS_CONSTRUCTOR_REGEXP =         NJS_PROTOTYPE_REGEXP,
+    NJS_CONSTRUCTOR_DATE =           NJS_PROTOTYPE_DATE,
+    NJS_CONSTRUCTOR_ERROR =          NJS_PROTOTYPE_ERROR,
+    NJS_CONSTRUCTOR_EVAL_ERROR =     NJS_PROTOTYPE_EVAL_ERROR,
+    NJS_CONSTRUCTOR_INTERNAL_ERROR = NJS_PROTOTYPE_INTERNAL_ERROR,
+    NJS_CONSTRUCTOR_RANGE_ERROR =    NJS_PROTOTYPE_RANGE_ERROR,
+    NJS_CONSTRUCTOR_REF_ERROR =      NJS_PROTOTYPE_REF_ERROR,
+    NJS_CONSTRUCTOR_SYNTAX_ERROR =   NJS_PROTOTYPE_SYNTAX_ERROR,
+    NJS_CONSTRUCTOR_TYPE_ERROR =     NJS_PROTOTYPE_TYPE_ERROR,
+    NJS_CONSTRUCTOR_URI_ERROR =      NJS_PROTOTYPE_URI_ERROR,
+    NJS_CONSTRUCTOR_MEMORY_ERROR =   NJS_PROTOTYPE_MEMORY_ERROR,
+#define NJS_CONSTRUCTOR_MAX    (NJS_CONSTRUCTOR_MEMORY_ERROR + 1)
 };
 
 
@@ -833,6 +867,23 @@ enum njs_function_e {
     njs_global_scope_index(NJS_CONSTRUCTOR_FUNCTION)
 #define NJS_INDEX_REGEXP         njs_global_scope_index(NJS_CONSTRUCTOR_REGEXP)
 #define NJS_INDEX_DATE           njs_global_scope_index(NJS_CONSTRUCTOR_DATE)
+#define NJS_INDEX_OBJECT_ERROR   njs_global_scope_index(NJS_CONSTRUCTOR_ERROR)
+#define NJS_INDEX_OBJECT_EVAL_ERROR                                           \
+    njs_global_scope_index(NJS_CONSTRUCTOR_EVAL_ERROR)
+#define NJS_INDEX_OBJECT_INTERNAL_ERROR                                       \
+    njs_global_scope_index(NJS_CONSTRUCTOR_INTERNAL_ERROR)
+#define NJS_INDEX_OBJECT_RANGE_ERROR                                          \
+    njs_global_scope_index(NJS_CONSTRUCTOR_RANGE_ERROR)
+#define NJS_INDEX_OBJECT_REF_ERROR                                            \
+    njs_global_scope_index(NJS_CONSTRUCTOR_REF_ERROR)
+#define NJS_INDEX_OBJECT_SYNTAX_ERROR                                         \
+    njs_global_scope_index(NJS_CONSTRUCTOR_SYNTAX_ERROR)
+#define NJS_INDEX_OBJECT_TYPE_ERROR                                           \
+    njs_global_scope_index(NJS_CONSTRUCTOR_TYPE_ERROR)
+#define NJS_INDEX_OBJECT_URI_ERROR                                            \
+    njs_global_scope_index(NJS_CONSTRUCTOR_URI_ERROR)
+#define NJS_INDEX_OBJECT_MEMORY_ERROR                                         \
+    njs_global_scope_index(NJS_CONSTRUCTOR_MEMORY_ERROR)
 
 #define NJS_INDEX_GLOBAL_RETVAL  njs_global_scope_index(NJS_CONSTRUCTOR_MAX)
 #define NJS_INDEX_GLOBAL_OFFSET  njs_scope_index(NJS_CONSTRUCTOR_MAX + 1, 0)
@@ -906,6 +957,14 @@ struct njs_vm_s {
     nxt_regex_context_t      *regex_context;
     nxt_regex_match_data_t   *single_match_data;
 
+    /*
+     * MemoryError is statically allocated immutable Error object
+     * with the generic type NJS_OBJECT_INTERNAL_ERROR but its own prototype
+     * object NJS_PROTOTYPE_MEMORY_ERROR.
+     */
+    njs_value_t              memory_error;
+    njs_object_t             memory_error_object;
+
     nxt_array_t              *code;  /* of njs_vm_code_t */
 
     nxt_trace_t              trace;
@@ -1117,14 +1176,8 @@ extern const njs_value_t  njs_string_native;
 extern const njs_value_t  njs_string_minus_infinity;
 extern const njs_value_t  njs_string_plus_infinity;
 extern const njs_value_t  njs_string_nan;
-
-extern const njs_value_t  njs_exception_syntax_error;
-extern const njs_value_t  njs_exception_reference_error;
-extern const njs_value_t  njs_exception_type_error;
-extern const njs_value_t  njs_exception_range_error;
-extern const njs_value_t  njs_exception_uri_error;
-extern const njs_value_t  njs_exception_memory_error;
-extern const njs_value_t  njs_exception_internal_error;
+extern const njs_value_t  njs_string_internal_error;
+extern const njs_value_t  njs_string_memory_error;
 
 extern const nxt_mem_proto_t     njs_array_mem_proto;
 extern const nxt_lvlhsh_proto_t  njs_object_hash_proto;
index 4f54dfc747c2b69b4dfe541ebf04166ec03094f6..2dd1f509e1726d0fe5fec772d9fed33dafbb0dfb 100644 (file)
@@ -522,6 +522,10 @@ njs_vm_retval(njs_vm_t *vm, nxt_str_t *retval)
 nxt_int_t
 njs_vm_exception(njs_vm_t *vm, nxt_str_t *retval)
 {
+    if (vm->top_frame != NULL) {
+        vm->top_frame->trap_tries = 0;
+    }
+
     return njs_value_to_ext_string(vm, retval, vm->exception);
 }
 
index 30c851914a0cda4e16d37182d36820e44ec0e552..5081a7b9e574807505d845347e34c38c5d426e01 100644 (file)
@@ -51,8 +51,8 @@ njs_test {
 }
 
 njs_test {
-    {"M\t"
-     "M\aath"}
+    {"Ma\t"
+     "Ma\ath"}
 }
 
 njs_test {
@@ -86,8 +86,8 @@ njs_test {
 }
 
 njs_test {
-    {"M\t"
-     "M\aath"}
+    {"Ma\t"
+     "Ma\ath"}
     {".\t\t"
      "Math.__proto__*Math.cbrt*Math.fround*Math.log2"}
 }
index 6a2385ecb2159aff740892b817d497a422b7352d..6e06776ecc88e5d807697dc4c0576e1db73308d2 100644 (file)
@@ -5161,6 +5161,262 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var chars = '𐒠'; chars.length +' '+ chars.charCodeAt(0)"),
       nxt_string("1 66720") },
 
+    /* Error object. */
+
+    { nxt_string("Error()"),
+      nxt_string("Error") },
+
+    { nxt_string("new Error()"),
+      nxt_string("Error") },
+
+    { nxt_string("Error('e')"),
+      nxt_string("Error: e") },
+
+    { nxt_string("var e = Error('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = Error('e'); e.name = ''; e"),
+      nxt_string("e") },
+
+    { nxt_string("var e = Error(); e.name = ''; e"),
+      nxt_string("") },
+
+    { nxt_string("var e = Error(); e.name = ''; e.message = 'e'; e"),
+      nxt_string("e") },
+
+    { nxt_string("Error('e').name + ': ' + Error('e').message"),
+      nxt_string("Error: e") },
+
+    { nxt_string("Error(1)"),
+      nxt_string("Error: 1") },
+
+    { nxt_string("Error.__proto__ == Function.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("Error.prototype.name"),
+      nxt_string("Error") },
+
+    { nxt_string("Error.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("Error.prototype.constructor == Error"),
+      nxt_string("true") },
+
+    { nxt_string("Error().__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("Error().__proto__.__proto__ == Object.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("EvalError('e')"),
+      nxt_string("EvalError: e") },
+
+    { nxt_string("InternalError('e')"),
+      nxt_string("InternalError: e") },
+
+    { nxt_string("RangeError('e')"),
+      nxt_string("RangeError: e") },
+
+    { nxt_string("ReferenceError('e')"),
+      nxt_string("ReferenceError: e") },
+
+    { nxt_string("SyntaxError('e')"),
+      nxt_string("SyntaxError: e") },
+
+    { nxt_string("TypeError('e')"),
+      nxt_string("TypeError: e") },
+
+    { nxt_string("URIError('e')"),
+      nxt_string("URIError: e") },
+
+    { nxt_string("MemoryError('e')"),
+      nxt_string("MemoryError") },
+
+    { nxt_string("EvalError('e').name + ': ' + EvalError('e').message"),
+      nxt_string("EvalError: e") },
+
+    { nxt_string("InternalError('e').name + ': ' + InternalError('e').message"),
+      nxt_string("InternalError: e") },
+
+    { nxt_string("RangeError('e').name + ': ' + RangeError('e').message"),
+      nxt_string("RangeError: e") },
+
+    { nxt_string("ReferenceError('e').name + ': ' + ReferenceError('e').message"),
+      nxt_string("ReferenceError: e") },
+
+    { nxt_string("SyntaxError('e').name + ': ' + SyntaxError('e').message"),
+      nxt_string("SyntaxError: e") },
+
+    { nxt_string("TypeError('e').name + ': ' + TypeError('e').message"),
+      nxt_string("TypeError: e") },
+
+    { nxt_string("URIError('e').name + ': ' + URIError('e').message"),
+      nxt_string("URIError: e") },
+
+    { nxt_string("MemoryError('e').name + ': ' + MemoryError('e').message"),
+      nxt_string("MemoryError: ") },
+
+    { nxt_string("var e = EvalError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = InternalError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = RangeError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = ReferenceError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = SyntaxError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = TypeError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    { nxt_string("var e = URIError('e'); e.name = 'E'; e"),
+      nxt_string("E: e") },
+
+    /* Memory object is immutable. */
+
+    { nxt_string("var e = MemoryError('e'); e.name = 'E'; e.message = 'e'; e"),
+      nxt_string("MemoryError") },
+
+    { nxt_string("EvalError.prototype.name"),
+      nxt_string("EvalError") },
+
+    { nxt_string("InternalError.prototype.name"),
+      nxt_string("InternalError") },
+
+    { nxt_string("RangeError.prototype.name"),
+      nxt_string("RangeError") },
+
+    { nxt_string("ReferenceError.prototype.name"),
+      nxt_string("ReferenceError") },
+
+    { nxt_string("SyntaxError.prototype.name"),
+      nxt_string("SyntaxError") },
+
+    { nxt_string("TypeError.prototype.name"),
+      nxt_string("TypeError") },
+
+    { nxt_string("URIError.prototype.name"),
+      nxt_string("URIError") },
+
+    { nxt_string("MemoryError.prototype.name"),
+      nxt_string("MemoryError") },
+
+    { nxt_string("EvalError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("InternalError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("RangeError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("ReferenceError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("SyntaxError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("TypeError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("URIError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("MemoryError.prototype.message"),
+      nxt_string("") },
+
+    { nxt_string("EvalError.prototype.constructor == EvalError"),
+      nxt_string("true") },
+
+    { nxt_string("RangeError.prototype.constructor == RangeError"),
+      nxt_string("true") },
+
+    { nxt_string("ReferenceError.prototype.constructor == ReferenceError"),
+      nxt_string("true") },
+
+    { nxt_string("SyntaxError.prototype.constructor == SyntaxError"),
+      nxt_string("true") },
+
+    { nxt_string("TypeError.prototype.constructor == TypeError"),
+      nxt_string("true") },
+
+    { nxt_string("URIError.prototype.constructor == URIError"),
+      nxt_string("true") },
+
+    { nxt_string("EvalError().__proto__ == EvalError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("RangeError().__proto__ == RangeError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("ReferenceError().__proto__ == ReferenceError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("SyntaxError().__proto__ == SyntaxError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("TypeError().__proto__ == TypeError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("URIError().__proto__ == URIError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("EvalError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("RangeError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("ReferenceError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("SyntaxError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("TypeError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("URIError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("MemoryError().__proto__ == MemoryError.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("MemoryError().__proto__.__proto__ == Error.prototype"),
+      nxt_string("true") },
+
+    { nxt_string("typeof Error()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof EvalError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof InternalError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof RangeError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof ReferenceError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof SyntaxError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof TypeError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof URIError()"),
+      nxt_string("object") },
+
+    { nxt_string("typeof MemoryError()"),
+      nxt_string("object") },
+
     /* Exceptions. */
 
     { nxt_string("throw null"),
@@ -5169,6 +5425,9 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var a; try { throw null } catch (e) { a = e } a"),
       nxt_string("null") },
 
+    { nxt_string("var a; try { throw Error('e') } catch (e) { a = e.message } a"),
+      nxt_string("e") },
+
     { nxt_string("try { throw null } catch (e) { throw e }"),
       nxt_string("") },
 
@@ -8202,6 +8461,21 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("JSON.stringify(RegExp())"),
       nxt_string("{}") },
 
+    { nxt_string("JSON.stringify(SyntaxError('e'))"),
+      nxt_string("{}") },
+
+    { nxt_string("JSON.stringify(URIError('e'))"),
+      nxt_string("{}") },
+
+    { nxt_string("var e = URIError('e'); e.name = 'E'; JSON.stringify(e)"),
+      nxt_string("{\"name\":\"E\"}") },
+
+    { nxt_string("var e = URIError('e'); e.message = 'E'; JSON.stringify(e)"),
+      nxt_string("{}") },
+
+    { nxt_string("var e = URIError('e'); e.foo = 'E'; JSON.stringify(e)"),
+      nxt_string("{\"foo\":\"E\"}") },
+
     /* Ignoring named properties of an array. */
 
     { nxt_string("var a = [1,2]; a.a = 1;"
index db1cdd703265f43740175e64da171782080e26f9..ec953cf3cc34cc0088b6614fd1a2afff323ea1d1 100644 (file)
@@ -40,6 +40,9 @@ nxt_upper_case(u_char c)
 }
 
 
+#define nxt_cpymem(dst, src, n)   (((u_char *) memcpy(dst, src, n)) + (n))
+
+
 #define nxt_strstr_eq(s1, s2)                                                 \
     (((s1)->length == (s2)->length)                                           \
      && (memcmp((s1)->start, (s2)->start, (s1)->length) == 0))