[njs] Constructor function prototypes now have correct types and...

Igor Sysoev igor at sysoev.ru
Tue Sep 13 13:20:19 UTC 2016


details:   http://hg.nginx.org/njs/rev/cb414901cccc
branches:  
changeset: 169:cb414901cccc
user:      Igor Sysoev <igor at sysoev.ru>
date:      Tue Sep 13 16:19:26 2016 +0300
description:
Constructor function prototypes now have correct types and values.

diffstat:

 njs/njs_array.c          |    3 +-
 njs/njs_array.h          |    9 --
 njs/njs_builtin.c        |   49 ++++++++++++--
 njs/njs_date.c           |    3 +-
 njs/njs_date.h           |    6 -
 njs/njs_function.c       |    6 +-
 njs/njs_object.c         |   52 +++++++++------
 njs/njs_object.h         |    6 -
 njs/njs_regexp.c         |    3 +-
 njs/njs_regexp.h         |   16 -----
 njs/njs_vm.c             |    8 +-
 njs/njs_vm.h             |  150 +++++++++++++++++++++++++++++++---------------
 njs/test/njs_unit_test.c |   48 +++++++++++++++
 13 files changed, 234 insertions(+), 125 deletions(-)

diffs (762 lines):

diff -r 19758fdcd554 -r cb414901cccc njs/njs_array.c
--- a/njs/njs_array.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_array.c	Tue Sep 13 16:19:26 2016 +0300
@@ -133,7 +133,8 @@ njs_array_alloc(njs_vm_t *vm, uint32_t l
     array->start = array->data;
     nxt_lvlhsh_init(&array->object.hash);
     nxt_lvlhsh_init(&array->object.shared_hash);
-    array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
+    array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY].object;
+    array->object.type = NJS_ARRAY;
     array->object.shared = 0;
     array->size = size;
     array->length = length;
diff -r 19758fdcd554 -r cb414901cccc njs/njs_array.h
--- a/njs/njs_array.h	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_array.h	Tue Sep 13 16:19:26 2016 +0300
@@ -10,15 +10,6 @@
 
 #define NJS_ARRAY_SPARE  8
 
-struct njs_array_s {
-    /* Must be aligned to njs_value_t. */
-    njs_object_t         object;
-    uint32_t             size;
-    uint32_t             length;
-    njs_value_t          *start;
-    njs_value_t          *data;
-};
-
 
 njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare);
 njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, u_char *start,
diff -r 19758fdcd554 -r cb414901cccc njs/njs_builtin.c
--- a/njs/njs_builtin.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_builtin.c	Tue Sep 13 16:19:26 2016 +0300
@@ -37,10 +37,11 @@ typedef struct {
 nxt_int_t
 njs_builtin_objects_create(njs_vm_t *vm)
 {
-    nxt_int_t       ret;
-    nxt_uint_t      i;
-    njs_object_t    *objects, *prototypes;
-    njs_function_t  *functions, *constructors;
+    nxt_int_t               ret;
+    nxt_uint_t              i;
+    njs_object_t            *objects;
+    njs_function_t          *functions, *constructors;
+    njs_object_prototype_t  *prototypes;
 
     static const njs_object_init_t    *prototype_init[] = {
         &njs_object_prototype_init,
@@ -53,6 +54,29 @@ njs_builtin_objects_create(njs_vm_t *vm)
         &njs_date_prototype_init,
     };
 
+    static const njs_object_prototype_t  prototype_values[] = {
+        { .object.type = NJS_OBJECT },
+        { .object.type = NJS_ARRAY },
+
+        /*
+         * The .object.type field must be initialzed after the .value field,
+         * otherwise SunC 5.9 treats the .value as .object.value or so.
+         */
+        { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0),
+                            .object.type = NJS_OBJECT_BOOLEAN } },
+
+        { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0),
+                            .object.type = NJS_OBJECT_NUMBER } },
+
+        { .object_value = { .value = njs_string(""),
+                            .object.type = NJS_OBJECT_STRING } },
+
+        { .object.type = NJS_FUNCTION },
+        { .object.type = NJS_REGEXP },
+
+        { .date =         { .time = NJS_NAN, .object.type = NJS_DATE } },
+    };
+
     static const njs_object_init_t    *constructor_init[] = {
         &njs_object_constructor_init,
         &njs_array_constructor_init,
@@ -172,7 +196,9 @@ njs_builtin_objects_create(njs_vm_t *vm)
     prototypes = vm->shared->prototypes;
 
     for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
-        ret = njs_object_hash_create(vm, &prototypes[i].shared_hash,
+        prototypes[i] = prototype_values[i];
+
+        ret = njs_object_hash_create(vm, &prototypes[i].object.shared_hash,
                                      prototype_init[i]->properties,
                                      prototype_init[i]->items);
         if (nxt_slow_path(ret != NXT_OK)) {
@@ -180,6 +206,9 @@ njs_builtin_objects_create(njs_vm_t *vm)
         }
     }
 
+    prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern =
+                                     vm->empty_regexp.data.u.regexp->pattern;
+
     constructors = vm->shared->constructors;
 
     for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
@@ -249,22 +278,24 @@ njs_builtin_objects_clone(njs_vm_t *vm)
     size_t        size;
     nxt_uint_t    i;
     njs_value_t   *values;
-    njs_object_t  *function_prototype;
+    njs_object_t  *object_prototype, *function_prototype;
 
     /*
      * Copy both prototypes and constructors arrays by one memcpy()
      * because they are stored together.
      */
-    size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t)
+    size = NJS_PROTOTYPE_MAX * sizeof(njs_object_prototype_t)
            + NJS_CONSTRUCTOR_MAX * sizeof(njs_function_t);
 
     memcpy(vm->prototypes, vm->shared->prototypes, size);
 
+    object_prototype = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
+
     for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
-        vm->prototypes[i].__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+        vm->prototypes[i].object.__proto__ = object_prototype;
     }
 
-    function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION];
+    function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object;
     values = vm->scopes[NJS_SCOPE_GLOBAL];
 
     for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
diff -r 19758fdcd554 -r cb414901cccc njs/njs_date.c
--- a/njs/njs_date.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_date.c	Tue Sep 13 16:19:26 2016 +0300
@@ -151,8 +151,9 @@ njs_date_constructor(njs_vm_t *vm, njs_v
 
         nxt_lvlhsh_init(&date->object.hash);
         nxt_lvlhsh_init(&date->object.shared_hash);
+        date->object.type = NJS_DATE;
         date->object.shared = 0;
-        date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE];
+        date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE].object;
 
         date->time = time;
 
diff -r 19758fdcd554 -r cb414901cccc njs/njs_date.h
--- a/njs/njs_date.h	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_date.h	Tue Sep 13 16:19:26 2016 +0300
@@ -8,12 +8,6 @@
 #define _NJS_DATE_H_INCLUDED_
 
 
-struct njs_date_s {
-    njs_object_t  object;
-    double        time;
-};
-
-
 njs_ret_t njs_date_constructor(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 
diff -r 19758fdcd554 -r cb414901cccc njs/njs_function.c
--- a/njs/njs_function.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_function.c	Tue Sep 13 16:19:26 2016 +0300
@@ -40,6 +40,7 @@ njs_function_alloc(njs_vm_t *vm)
          */
 
         function->object.shared_hash = vm->shared->function_prototype_hash;
+        function->object.type = NJS_FUNCTION;
         function->object.shared = 1;
         function->args_offset = 1;
 
@@ -69,7 +70,8 @@ njs_function_value_copy(njs_vm_t *vm, nj
 
     if (nxt_fast_path(function != NULL)) {
         *function = *value->data.u.function;
-        function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+        function->object.__proto__ =
+                                &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
         function->object.shared = 0;
         value->data.u.function = function;
     }
@@ -527,7 +529,7 @@ njs_function_prototype_bind(njs_vm_t *vm
 
     *function = *args[0].data.u.function;
 
-    function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+    function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
     function->object.shared = 0;
 
     if (nargs == 1) {
diff -r 19758fdcd554 -r cb414901cccc njs/njs_object.c
--- a/njs/njs_object.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_object.c	Tue Sep 13 16:19:26 2016 +0300
@@ -35,7 +35,8 @@ njs_object_alloc(njs_vm_t *vm)
     if (nxt_fast_path(object != NULL)) {
         nxt_lvlhsh_init(&object->hash);
         nxt_lvlhsh_init(&object->shared_hash);
-        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
+        object->type = NJS_OBJECT;
         object->shared = 0;
     }
 
@@ -58,7 +59,7 @@ njs_object_value_copy(njs_vm_t *vm, njs_
 
     if (nxt_fast_path(object != NULL)) {
         *object = *value->data.u.object;
-        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
         object->shared = 0;
         value->data.u.object = object;
     }
@@ -78,10 +79,11 @@ njs_object_value_alloc(njs_vm_t *vm, con
     if (nxt_fast_path(ov != NULL)) {
         nxt_lvlhsh_init(&ov->object.hash);
         nxt_lvlhsh_init(&ov->object.shared_hash);
+        ov->object.type = njs_object_value_type(type);
         ov->object.shared = 0;
 
         index = njs_primitive_prototype_index(type);
-        ov->object.__proto__ = &vm->prototypes[index];
+        ov->object.__proto__ = &vm->prototypes[index].object;
 
         ov->value = *value;
     }
@@ -258,7 +260,7 @@ njs_object_constructor(njs_vm_t *vm, njs
                 return NXT_ERROR;
             }
 
-            type = NJS_OBJECT + value->type;
+            type = njs_object_value_type(value->type);
 
         } else {
             vm->exception = &njs_exception_type_error;
@@ -324,6 +326,7 @@ njs_object_create(njs_vm_t *vm, njs_valu
 njs_ret_t
 njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
 {
+    nxt_uint_t    index;
     njs_object_t  *proto;
 
     /*
@@ -331,14 +334,15 @@ njs_primitive_prototype_get_proto(njs_vm
      * and have to return different results for primitive type and for objects.
      */
     if (njs_is_object(value)) {
-         proto = value->data.u.object->__proto__;
+        proto = value->data.u.object->__proto__;
 
     } else {
-         proto = &vm->prototypes[njs_primitive_prototype_index(value->type)];
+        index = njs_primitive_prototype_index(value->type);
+        proto = &vm->prototypes[index].object;
     }
 
     vm->retval.data.u.object = proto;
-    vm->retval.type = NJS_OBJECT;
+    vm->retval.type = proto->type;
     vm->retval.data.truth = 1;
 
     return NXT_OK;
@@ -364,7 +368,7 @@ njs_object_prototype_create(njs_vm_t *vm
 
     if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
         proto = njs_property_prototype_create(vm, &function->object.hash,
-                                              &vm->prototypes[index]);
+                                              &vm->prototypes[index].object);
     }
 
     if (proto == NULL) {
@@ -395,7 +399,7 @@ njs_property_prototype_create(njs_vm_t *
     /* GC */
 
     prop->value.data.u.object = prototype;
-    prop->value.type = NJS_OBJECT;
+    prop->value.type = prototype->type;
     prop->value.data.truth = 1;
 
     prop->enumerable = 0;
@@ -469,7 +473,7 @@ njs_object_prototype_get_proto(njs_vm_t 
 
     if (nxt_fast_path(proto != NULL)) {
         vm->retval.data.u.object = proto;
-        vm->retval.type = NJS_OBJECT;
+        vm->retval.type = proto->type;
         vm->retval.data.truth = 1;
 
     } else {
@@ -489,23 +493,25 @@ njs_object_prototype_get_proto(njs_vm_t 
 static njs_ret_t
 njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
 {
-    int32_t       index;
-    njs_value_t   *cons;
-    njs_object_t  *prototype;
+    int32_t                 index;
+    njs_value_t             *cons;
+    njs_object_t            *object;
+    njs_object_prototype_t  *prototype;
 
     if (njs_is_object(value)) {
-        prototype = value->data.u.object;
+        object = value->data.u.object;
 
         do {
+            prototype = (njs_object_prototype_t *) object;
             index = prototype - vm->prototypes;
 
             if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
                 goto found;
             }
 
-            prototype = prototype->__proto__;
+            object = object->__proto__;
 
-        } while (prototype != NULL);
+        } while (object != NULL);
 
         nxt_thread_log_alert("prototype not found");
 
@@ -518,7 +524,7 @@ njs_object_prototype_create_constructor(
 
 found:
 
-    cons = njs_property_constructor_create(vm, &prototype->hash,
+    cons = njs_property_constructor_create(vm, &prototype->object.hash,
                                           &vm->scopes[NJS_SCOPE_GLOBAL][index]);
     if (nxt_fast_path(cons != NULL)) {
         vm->retval = *cons;
@@ -604,8 +610,9 @@ njs_ret_t
 njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    int32_t       index;
-    njs_object_t  *prototype;
+    int32_t                 index;
+    njs_object_t            *object;
+    njs_object_prototype_t  *prototype;
 
     static const njs_value_t  *class_name[] = {
         /* Primitives. */
@@ -633,9 +640,10 @@ njs_object_prototype_to_string(njs_vm_t 
     index = args[0].type;
 
     if (njs_is_object(&args[0])) {
-        prototype = args[0].data.u.object;
+        object = args[0].data.u.object;
 
         do {
+            prototype = (njs_object_prototype_t *) object;
             index = prototype - vm->prototypes;
 
             if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
@@ -643,9 +651,9 @@ njs_object_prototype_to_string(njs_vm_t 
                 goto found;
             }
 
-            prototype = prototype->__proto__;
+            object = object->__proto__;
 
-        } while (prototype != NULL);
+        } while (object != NULL);
 
         nxt_thread_log_alert("prototype not found");
 
diff -r 19758fdcd554 -r cb414901cccc njs/njs_object.h
--- a/njs/njs_object.h	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_object.h	Tue Sep 13 16:19:26 2016 +0300
@@ -8,12 +8,6 @@
 #define _NJS_OBJECT_H_INCLUDED_
 
 
-struct njs_object_value_s {
-    njs_object_t                object;
-    njs_value_t                 value;
-};
-
-
 typedef enum {
     NJS_PROPERTY = 0,
     NJS_GETTER,
diff -r 19758fdcd554 -r cb414901cccc njs/njs_regexp.c
--- a/njs/njs_regexp.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_regexp.c	Tue Sep 13 16:19:26 2016 +0300
@@ -466,7 +466,8 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regex
     if (nxt_fast_path(regexp != NULL)) {
         nxt_lvlhsh_init(&regexp->object.hash);
         nxt_lvlhsh_init(&regexp->object.shared_hash);
-        regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP];
+        regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP].object;
+        regexp->object.type = NJS_REGEXP;
         regexp->object.shared = 0;
         regexp->last_index = 0;
         regexp->pattern = pattern;
diff -r 19758fdcd554 -r cb414901cccc njs/njs_regexp.h
--- a/njs/njs_regexp.h	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_regexp.h	Tue Sep 13 16:19:26 2016 +0300
@@ -16,22 +16,6 @@ typedef enum {
 } njs_regexp_flags_t;
 
 
-struct njs_regexp_s {
-    /* Must be aligned to njs_value_t. */
-    njs_object_t          object;
-
-    uint32_t              last_index;
-
-    njs_regexp_pattern_t  *pattern;
-
-    /*
-     * This string value can be unaligned since
-     * it never used in nJSVM operations.
-     */
-    njs_value_t           string;
-};
-
-
 njs_ret_t njs_regexp_init(njs_vm_t *vm);
 njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
diff -r 19758fdcd554 -r cb414901cccc njs/njs_vm.c
--- a/njs/njs_vm.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_vm.c	Tue Sep 13 16:19:26 2016 +0300
@@ -403,7 +403,8 @@ njs_vmcode_function(njs_vm_t *vm, njs_va
     function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
 
     if (nxt_fast_path(function != NULL)) {
-        function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+        function->object.__proto__ =
+                                &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
         function->args_offset = 1;
 
         code = (njs_vmcode_function_t *) vm->current;
@@ -929,7 +930,8 @@ njs_property_query(njs_vm_t *vm, njs_pro
             return NJS_PRIMITIVE_VALUE;
         }
 
-        obj = &vm->prototypes[njs_primitive_prototype_index(object->type)];
+        index = njs_primitive_prototype_index(object->type);
+        obj = &vm->prototypes[index].object;
         break;
 
     case NJS_STRING:
@@ -937,7 +939,7 @@ njs_property_query(njs_vm_t *vm, njs_pro
             return NXT_DECLINED;
         }
 
-        obj = &vm->prototypes[NJS_PROTOTYPE_STRING];
+        obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object;
         break;
 
     case NJS_ARRAY:
diff -r 19758fdcd554 -r cb414901cccc njs/njs_vm.h
--- a/njs/njs_vm.h	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/njs_vm.h	Tue Sep 13 16:19:26 2016 +0300
@@ -111,6 +111,7 @@ typedef njs_ret_t (*njs_function_native_
 
 
 typedef struct njs_string_s           njs_string_t;
+typedef struct njs_object_s           njs_object_t;
 typedef struct njs_object_init_s      njs_object_init_t;
 typedef struct njs_object_value_s     njs_object_value_t;
 typedef struct njs_array_s            njs_array_t;
@@ -123,53 +124,6 @@ typedef struct njs_native_frame_s     nj
 typedef struct njs_property_next_s    njs_property_next_t;
 
 
-typedef struct njs_object_s           njs_object_t;
-
-struct njs_object_s {
-    /* A private hash of njs_object_prop_t. */
-    nxt_lvlhsh_t                      hash;
-
-    /* A shared hash of njs_object_prop_t. */
-    nxt_lvlhsh_t                      shared_hash;
-
-    /* An object __proto__. */
-    njs_object_t                      *__proto__;
-
-    uint32_t                          shared;  /* 1 bit */
-};
-
-
-#define NJS_ARGS_TYPES_MAX            5
-
-struct njs_function_s {
-    njs_object_t                      object;
-
-    uint8_t                           args_types[NJS_ARGS_TYPES_MAX];
-    uint8_t                           args_offset;
-
-    /*
-     * TODO Shared
-     * When function object is used as value: in assignments,
-     * as function argument, as property and as object to get properties.
-     */
-
-#if (NXT_64BIT)
-    uint8_t                           native;
-    uint8_t                           continuation_size;
-#else
-    uint8_t                           native;
-    uint8_t                           continuation_size;
-#endif
-
-    union {
-        njs_function_lambda_t         *lambda;
-        njs_function_native_t         native;
-    } u;
-
-    njs_value_t                       *bound;
-};
-
-
 typedef struct njs_continuation_s     njs_continuation_t;
 
 struct njs_continuation_s {
@@ -246,6 +200,97 @@ union njs_value_s {
 };
 
 
+struct njs_object_s {
+    /* A private hash of njs_object_prop_t. */
+    nxt_lvlhsh_t                      hash;
+
+    /* A shared hash of njs_object_prop_t. */
+    nxt_lvlhsh_t                      shared_hash;
+
+    /* An object __proto__. */
+    njs_object_t                      *__proto__;
+
+    /* The type is used in constructor prototypes. */
+    njs_value_type_t                  type:8;
+    uint8_t                           shared;  /* 1 bit */
+};
+
+
+struct njs_object_value_s {
+    njs_object_t                      object;
+    /* The value can be unaligned since it never used in nJSVM operations. */
+    njs_value_t                       value;
+};
+
+
+struct njs_array_s {
+    njs_object_t                      object;
+    uint32_t                          size;
+    uint32_t                          length;
+    njs_value_t                       *start;
+    njs_value_t                       *data;
+};
+
+
+#define NJS_ARGS_TYPES_MAX            5
+
+struct njs_function_s {
+    njs_object_t                      object;
+
+    uint8_t                           args_types[NJS_ARGS_TYPES_MAX];
+    uint8_t                           args_offset;
+
+    /*
+     * TODO Shared
+     * When function object is used as value: in assignments,
+     * as function argument, as property and as object to get properties.
+     */
+
+#if (NXT_64BIT)
+    uint8_t                           native;
+    uint8_t                           continuation_size;
+#else
+    uint8_t                           native;
+    uint8_t                           continuation_size;
+#endif
+
+    union {
+        njs_function_lambda_t         *lambda;
+        njs_function_native_t         native;
+    } u;
+
+    njs_value_t                       *bound;
+};
+
+
+struct njs_regexp_s {
+    njs_object_t                      object;
+    uint32_t                          last_index;
+    njs_regexp_pattern_t              *pattern;
+    /*
+     * This string value can be unaligned since
+     * it never used in nJSVM operations.
+     */
+    njs_value_t                       string;
+};
+
+
+struct njs_date_s {
+    njs_object_t                      object;
+    double                            time;
+};
+
+
+typedef union {
+    njs_object_t                      object;
+    njs_object_value_t                object_value;
+    njs_array_t                       array;
+    njs_function_t                    function;
+    njs_regexp_t                      regexp;
+    njs_date_t                        date;
+} njs_object_prototype_t;
+
+
 #define njs_value(_type, _truth, _number) {                                   \
     .data = {                                                                 \
         .type = _type,                                                        \
@@ -367,6 +412,10 @@ typedef njs_ret_t (*njs_vmcode_operation
     (((value)->type & NJS_OBJECT) != 0)
 
 
+#define njs_object_value_type(type)                                           \
+    (type + NJS_OBJECT)
+
+
 #define njs_is_array(value)                                                   \
     ((value)->type == NJS_ARRAY)
 
@@ -683,6 +732,9 @@ enum njs_prototypes_e {
 #define njs_primitive_prototype_index(type)                                   \
     (NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
 
+#define njs_prototype_type(index)                                             \
+    (index + NJS_OBJECT)
+
 
 enum njs_constructor_e {
     NJS_CONSTRUCTOR_OBJECT =   NJS_PROTOTYPE_OBJECT,
@@ -788,7 +840,7 @@ struct njs_vm_s {
      * they are copied from njs_vm_shared_t by single memcpy()
      * in njs_builtin_objects_clone().
      */
-    njs_object_t             prototypes[NJS_PROTOTYPE_MAX];
+    njs_object_prototype_t   prototypes[NJS_PROTOTYPE_MAX];
     njs_function_t           constructors[NJS_CONSTRUCTOR_MAX];
 
     nxt_mem_cache_pool_t     *mem_cache_pool;
@@ -829,7 +881,7 @@ struct njs_vm_shared_s {
      * The prototypes and constructors arrays must be togther because they are
      * copied to njs_vm_t by single memcpy() in njs_builtin_objects_clone().
      */
-    njs_object_t             prototypes[NJS_PROTOTYPE_MAX];
+    njs_object_prototype_t   prototypes[NJS_PROTOTYPE_MAX];
     njs_function_t           constructors[NJS_CONSTRUCTOR_MAX];
 };
 
diff -r 19758fdcd554 -r cb414901cccc njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Thu Sep 01 16:12:31 2016 +0300
+++ b/njs/test/njs_unit_test.c	Tue Sep 13 16:19:26 2016 +0300
@@ -4097,6 +4097,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Object.prototype.__proto__ === null"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(Object.prototype)"),
+      nxt_string("[object Object]") },
+
+    { nxt_string("Object.prototype"),
+      nxt_string("[object Object]") },
+
     { nxt_string("Object.constructor === Function"),
       nxt_string("true") },
 
@@ -4154,6 +4160,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Array.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(Array.prototype)"),
+      nxt_string("[object Array]") },
+
+    { nxt_string("Array.prototype"),
+      nxt_string("") },
+
     { nxt_string("Array.constructor === Function"),
       nxt_string("true") },
 
@@ -4211,6 +4223,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Boolean.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(Boolean.prototype)"),
+      nxt_string("[object Boolean]") },
+
+    { nxt_string("Boolean.prototype"),
+      nxt_string("false") },
+
     { nxt_string("Boolean.constructor === Function"),
       nxt_string("true") },
 
@@ -4264,6 +4282,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Number.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(Number.prototype)"),
+      nxt_string("[object Number]") },
+
+    { nxt_string("Number.prototype"),
+      nxt_string("0") },
+
     { nxt_string("Number.constructor === Function"),
       nxt_string("true") },
 
@@ -4314,6 +4338,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("String.__proto__ === Function.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(String.prototype)"),
+      nxt_string("[object String]") },
+
+    { nxt_string("String.prototype"),
+      nxt_string("") },
+
     { nxt_string("String.prototype.length"),
       nxt_string("0") },
 
@@ -4359,6 +4389,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Function.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(Function.prototype)"),
+      nxt_string("[object Function]") },
+
+    { nxt_string("Function.prototype"),
+      nxt_string("[object Function]") },
+
     { nxt_string("Function.constructor === Function"),
       nxt_string("true") },
 
@@ -4389,6 +4425,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("RegExp.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Object.prototype.toString.call(RegExp.prototype)"),
+      nxt_string("[object RegExp]") },
+
+    { nxt_string("RegExp.prototype"),
+      nxt_string("/(?:)/") },
+
     { nxt_string("RegExp.constructor === Function"),
       nxt_string("true") },
 
@@ -4801,6 +4843,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Date.prototype.__proto__ === Object.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Date.prototype"),
+      nxt_string("Invalid Date") },
+
+    { nxt_string("Date.prototype.valueOf()"),
+      nxt_string("NaN") },
+
     { nxt_string("Date.constructor === Function"),
       nxt_string("true") },
 



More information about the nginx-devel mailing list