[njs] Object.defineProperty() method.

Dmitry Volyntsev xeioex at nginx.com
Wed Jun 7 14:59:38 UTC 2017


details:   http://hg.nginx.org/njs/rev/a0bc58cc65d5
branches:  
changeset: 356:a0bc58cc65d5
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Jun 07 17:57:40 2017 +0300
description:
Object.defineProperty() method.

diffstat:

 njs/njs_object.c         |  112 +++++++++++++++++++++++++++++++++++++++++++++++
 njs/njs_object_hash.h    |   51 +++++++++++++++++++++
 njs/njs_vm.c             |    4 +-
 njs/test/njs_unit_test.c |   58 ++++++++++++++++++++++++
 4 files changed, 224 insertions(+), 1 deletions(-)

diffs (291 lines):

diff -r edf64bf9677c -r a0bc58cc65d5 njs/njs_object.c
--- a/njs/njs_object.c	Wed Jun 07 16:36:17 2017 +0300
+++ b/njs/njs_object.c	Wed Jun 07 17:57:40 2017 +0300
@@ -412,6 +412,109 @@ njs_object_keys(njs_vm_t *vm, njs_value_
 }
 
 
+static njs_ret_t
+njs_object_define_property(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    nxt_int_t           ret;
+    nxt_str_t           key;
+    njs_value_t         *name;
+    njs_object_t        *object, *descriptor;
+    njs_object_prop_t   *prop, *pr;
+    nxt_lvlhsh_query_t  lhq, pq;
+
+    if (nargs < 4 || !njs_is_object(&args[1]) || !njs_is_object(&args[3])) {
+        vm->exception = &njs_exception_type_error;
+        return NXT_ERROR;
+    }
+
+    object = args[1].data.u.object;
+    name = &args[2];
+    descriptor = args[3].data.u.object;
+
+    if (name->short_string.size != NJS_STRING_LONG) {
+        key.start = name->short_string.start;
+        key.length = name->short_string.length;
+
+    } else {
+        key.start = name->data.u.string->start;
+        key.length = name->data.string_size;
+    }
+
+    lhq.key = key;
+    lhq.key_hash = nxt_djb_hash(key.start, key.length);
+    lhq.proto = &njs_object_hash_proto;
+
+    ret = nxt_lvlhsh_find(&object->hash, &lhq);
+
+    if (ret != NXT_OK) {
+        prop = njs_object_prop_alloc(vm, name);
+
+        if (nxt_slow_path(prop == NULL)) {
+            return NXT_ERROR;
+        }
+
+        prop->configurable = 0;
+        prop->enumerable = 0;
+        prop->writable = 0;
+
+        lhq.value = prop;
+
+    } else {
+        prop = lhq.value;
+    }
+
+    pq.key = nxt_string_value("value");
+    pq.key_hash = NJS_VALUE_HASH;
+    pq.proto = &njs_object_hash_proto;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+
+    if (pr != NULL) {
+        prop->value = pr->value;
+    }
+
+    pq.key = nxt_string_value("configurable");
+    pq.key_hash = NJS_CONFIGURABLE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+
+    if (pr != NULL) {
+        prop->configurable = pr->value.data.truth;
+    }
+
+    pq.key = nxt_string_value("enumerable");
+    pq.key_hash = NJS_ENUMERABLE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+
+    if (pr != NULL) {
+        prop->enumerable = pr->value.data.truth;
+    }
+
+    pq.key = nxt_string_value("writable");
+    pq.key_hash = NJS_WRITABABLE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+
+    if (pr != NULL) {
+        prop->writable = pr->value.data.truth;
+    }
+
+    lhq.replace = 0;
+    lhq.pool = vm->mem_cache_pool;
+
+    ret = nxt_lvlhsh_insert(&object->hash, &lhq);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return NXT_ERROR;
+    }
+
+    vm->retval = args[1];
+
+    return NXT_OK;
+}
+
+
 /*
  * The __proto__ property of booleans, numbers and strings primitives,
  * of objects created by Boolean(), Number(), and String() constructors,
@@ -558,6 +661,15 @@ static const njs_object_prop_t  njs_obje
         .value = njs_native_function(njs_object_keys, 0,
                                      NJS_SKIP_ARG, NJS_OBJECT_ARG),
     },
+
+    /* Object.defineProperty(). */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("defineProperty"),
+        .value = njs_native_function(njs_object_define_property, 0,
+                                     NJS_SKIP_ARG, NJS_OBJECT_ARG,
+                                     NJS_STRING_ARG, NJS_OBJECT_ARG),
+    },
 };
 
 
diff -r edf64bf9677c -r a0bc58cc65d5 njs/njs_object_hash.h
--- a/njs/njs_object_hash.h	Wed Jun 07 16:36:17 2017 +0300
+++ b/njs/njs_object_hash.h	Wed Jun 07 17:57:40 2017 +0300
@@ -8,6 +8,22 @@
 #define _NJS_OBJECT_HASH_H_INCLUDED_
 
 
+#define NJS_CONFIGURABLE_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_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(NXT_DJB_HASH_INIT,                                       \
+        'c'), 'o'), 'n'), 'f'), 'i'), 'g'), 'u'), 'r'), 'a'), 'b'), 'l'), 'e')
+
+
 #define NJS_CONSTRUCTOR_HASH                                                  \
     nxt_djb_hash_add(                                                         \
     nxt_djb_hash_add(                                                         \
@@ -23,6 +39,20 @@
         'c'), 'o'), 'n'), 's'), 't'), 'r'), 'u'), 'c'), 't'), 'o'), 'r')
 
 
+#define NJS_ENUMERABLE_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_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(NXT_DJB_HASH_INIT,                                       \
+        'e'), 'n'), 'u'), 'm'), 'e'), 'r'), 'a'), 'b'), 'l'), 'e')
+
+
 #define NJS_INDEX_HASH                                                        \
     nxt_djb_hash_add(                                                         \
     nxt_djb_hash_add(                                                         \
@@ -74,6 +104,15 @@
         't'), 'o'), 'S'), 't'), 'r'), 'i'), 'n'), 'g')
 
 
+#define NJS_VALUE_HASH                                                        \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(                                                         \
+    nxt_djb_hash_add(NXT_DJB_HASH_INIT,                                       \
+        'v'), 'a'), 'l'), 'u'), 'e')
+
+
 #define NJS_VALUE_OF_HASH                                                     \
     nxt_djb_hash_add(                                                         \
     nxt_djb_hash_add(                                                         \
@@ -100,4 +139,16 @@
         't'), 'o'), 'I'), 'S'), 'O'), 'S'), 't'), 'r'), 'i'), 'n'), 'g')
 
 
+#define NJS_WRITABABLE_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_add(NXT_DJB_HASH_INIT,                                       \
+        'w'), 'r'), 'i'), 't'), 'a'), 'b'), 'l'), 'e')
+
+
 #endif /* _NJS_OBJECT_HASH_H_INCLUDED_ */
diff -r edf64bf9677c -r a0bc58cc65d5 njs/njs_vm.c
--- a/njs/njs_vm.c	Wed Jun 07 16:36:17 2017 +0300
+++ b/njs/njs_vm.c	Wed Jun 07 17:57:40 2017 +0300
@@ -746,7 +746,9 @@ njs_vmcode_property_set(njs_vm_t *vm, nj
         return ret;
     }
 
-    prop->value = *value;
+    if (prop->writable) {
+        prop->value = *value;
+    }
 
     return sizeof(njs_vmcode_prop_set_t);
 }
diff -r edf64bf9677c -r a0bc58cc65d5 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Wed Jun 07 16:36:17 2017 +0300
+++ b/njs/test/njs_unit_test.c	Wed Jun 07 17:57:40 2017 +0300
@@ -5874,6 +5874,64 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Object.keys(1)"),
       nxt_string("TypeError") },
 
+    { nxt_string("var o = {}; Object.defineProperty(o, 'a', {}); o.a"),
+      nxt_string("undefined") },
+
+    { nxt_string("Object.defineProperty({}, 'a', {value:1})"),
+      nxt_string("[object Object]") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o, 'a', {value:1}); o.a"),
+      nxt_string("1") },
+
+    { nxt_string("var o = {a:1, c:2}; Object.defineProperty(o, 'b', {});"
+                 "Object.keys(o)"),
+      nxt_string("a,c") },
+
+    { nxt_string("var o = {a:1, c:2};"
+                 "Object.defineProperty(o, 'b', {enumerable:false});"
+                 "Object.keys(o)"),
+      nxt_string("a,c") },
+
+    { nxt_string("var o = {a:1, c:3};"
+                 "Object.defineProperty(o, 'b', {enumerable:true});"
+                 "Object.keys(o)"),
+      nxt_string("a,c,b") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o, 'a', {}); o.a = 1; o.a"),
+      nxt_string("undefined") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o, 'a', {writable:false});"
+                 "o.a = 1; o.a"),
+      nxt_string("undefined") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o, 'a', {writable:true});"
+                 "o.a = 1; o.a"),
+      nxt_string("1") },
+
+    { nxt_string("var o = {};"
+                 "Object.defineProperty(o, 'a', {value:1}); delete o.a; o.a"),
+      nxt_string("1") },
+
+    { nxt_string("var o = {};"
+                 "Object.defineProperty(o, 'a', {value:1, configurable:true});"
+                 "delete o.a; o.a"),
+      nxt_string("undefined") },
+
+    { nxt_string("var o = {};"
+                 "Object.defineProperty(o, 'a', {value:1, configurable:false});"
+                 "delete o.a; o.a"),
+      nxt_string("1") },
+
+    { nxt_string("var o = {};"
+                 "Object.defineProperty(o, 'a', Object.create({value:2})); o.a"),
+      nxt_string("2") },
+
+    { nxt_string("var o = {}; Object.defineProperty()"),
+      nxt_string("TypeError") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o)"),
+      nxt_string("TypeError") },
+
     { nxt_string("var d = new Date(''); d +' '+ d.getTime()"),
       nxt_string("Invalid Date NaN") },
 


More information about the nginx-devel mailing list