[njs] Error builtin objects.

Dmitry Volyntsev xeioex at nginx.com
Fri Nov 17 16:06:04 UTC 2017


details:   http://hg.nginx.org/njs/rev/5bc8d7c25e4f
branches:  
changeset: 420:5bc8d7c25e4f
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Nov 17 18:55:07 2017 +0300
description:
Error builtin objects.

diffstat:

 Makefile                     |   16 +
 njs/njs_array.c              |    9 +-
 njs/njs_boolean.c            |    5 +-
 njs/njs_builtin.c            |   87 ++++-
 njs/njs_date.c               |    5 +-
 njs/njs_error.c              |  865 +++++++++++++++++++++++++++++++++++++++++++
 njs/njs_error.h              |   77 +++
 njs/njs_function.c           |   14 +-
 njs/njs_generator.c          |   14 +-
 njs/njs_json.c               |  100 +---
 njs/njs_lexer_keyword.c      |    9 +
 njs/njs_number.c             |    7 +-
 njs/njs_object.c             |   71 ++-
 njs/njs_object_hash.h        |   19 +
 njs/njs_parser.c             |   36 +
 njs/njs_parser.h             |    9 +
 njs/njs_regexp.c             |    9 +-
 njs/njs_string.c             |   15 +-
 njs/njs_vm.c                 |   57 ++-
 njs/njs_vm.h                 |  131 ++++-
 njs/njscript.c               |    4 +
 njs/test/njs_expect_test.exp |    8 +-
 njs/test/njs_unit_test.c     |  274 +++++++++++++
 nxt/nxt_string.h             |    3 +
 24 files changed, 1661 insertions(+), 183 deletions(-)

diffs (truncated from 2877 to 1000 lines):

diff -r a6af47aab3f2 -r 5bc8d7c25e4f Makefile
--- a/Makefile	Fri Nov 17 18:55:07 2017 +0300
+++ b/Makefile	Fri Nov 17 18:55:07 2017 +0300
@@ -20,6 +20,7 @@ NXT_BUILDDIR =	build
 	$(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 =	build
 		$(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 @@ dist:
 		-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 \
diff -r a6af47aab3f2 -r 5bc8d7c25e4f njs/njs_array.c
--- a/njs/njs_array.c	Fri Nov 17 18:55:07 2017 +0300
+++ b/njs/njs_array.c	Fri Nov 17 18:55:07 2017 +0300
@@ -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_
         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,
         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, nj
         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_
                                                          unused);
 type_error:
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
diff -r a6af47aab3f2 -r 5bc8d7c25e4f njs/njs_boolean.c
--- a/njs/njs_boolean.c	Fri Nov 17 18:55:07 2017 +0300
+++ b/njs/njs_boolean.c	Fri Nov 17 18:55:07 2017 +0300
@@ -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 
             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
             value = &value->data.u.object_value->value;
 
         } else {
-            vm->exception = &njs_exception_type_error;
+            njs_exception_type_error(vm, NULL, NULL);
             return NXT_ERROR;
         }
     }
diff -r a6af47aab3f2 -r 5bc8d7c25e4f njs/njs_builtin.c
--- a/njs/njs_builtin.c	Fri Nov 17 18:55:07 2017 +0300
+++ b/njs/njs_builtin.c	Fri Nov 17 18:55:07 2017 +0300
@@ -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_
     &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_construc
     &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];
 
diff -r a6af47aab3f2 -r 5bc8d7c25e4f njs/njs_date.c
--- a/njs/njs_date.c	Fri Nov 17 18:55:07 2017 +0300
+++ b/njs/njs_date.c	Fri Nov 17 18:55:07 2017 +0300
@@ -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_
         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,
         }
     }
 
-    vm->exception = &njs_exception_type_error;
+    njs_exception_type_error(vm, NULL, NULL);
 
     return NXT_ERROR;
 }
diff -r a6af47aab3f2 -r 5bc8d7c25e4f njs/njs_error.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_error.c	Fri Nov 17 18:55:07 2017 +0300
@@ -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[] =
+{


More information about the nginx-devel mailing list