[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