[njs] Fixed Object.defineProperty() for shared descriptors.
Dmitry Volyntsev
xeioex at nginx.com
Tue Jun 4 16:49:05 UTC 2019
details: https://hg.nginx.org/njs/rev/8b27db801cd3
branches:
changeset: 1000:8b27db801cd3
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Jun 04 19:38:50 2019 +0300
description:
Fixed Object.defineProperty() for shared descriptors.
This closes #172 issue on Github.
diffstat:
njs/njs_object.c | 33 ++++++++++++++++++++++++++-------
njs/njs_object.h | 2 +-
njs/njs_vm.c | 2 +-
njs/test/njs_unit_test.c | 12 ++++++++++++
4 files changed, 40 insertions(+), 9 deletions(-)
diffs (121 lines):
diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.c
--- a/njs/njs_object.c Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_object.c Tue Jun 04 19:38:50 2019 +0300
@@ -708,7 +708,7 @@ njs_external_property_delete(njs_vm_t *v
njs_ret_t
-njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
+njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
{
nxt_int_t ret;
njs_function_t *function;
@@ -727,6 +727,20 @@ njs_method_private_copy(njs_vm_t *vm, nj
shared = pq->lhq.value;
*prop = *shared;
+ pq->lhq.replace = 0;
+ pq->lhq.value = prop;
+ pq->lhq.pool = vm->mem_pool;
+
+ ret = nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NXT_ERROR;
+ }
+
+ if (!njs_is_function(&prop->value)) {
+ return NXT_OK;
+ }
+
function = njs_function_value_copy(vm, &prop->value);
if (nxt_slow_path(function == NULL)) {
return NXT_ERROR;
@@ -759,11 +773,7 @@ njs_method_private_copy(njs_vm_t *vm, nj
return NXT_ERROR;
}
- pq->lhq.replace = 0;
- pq->lhq.value = prop;
- pq->lhq.pool = vm->mem_pool;
-
- return nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
+ return NXT_OK;
}
@@ -1900,10 +1910,19 @@ njs_define_property(njs_vm_t *vm, njs_va
/* Updating existing prop. */
+ if (nxt_slow_path(pq.shared)) {
+ ret = njs_prop_private_copy(vm, &pq);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+ }
+
current = pq.lhq.value;
switch (current->type) {
case NJS_PROPERTY:
+ case NJS_METHOD:
break;
case NJS_PROPERTY_REF:
@@ -2043,7 +2062,7 @@ njs_object_property_descriptor(njs_vm_t
case NJS_METHOD:
if (pq.shared) {
- ret = njs_method_private_copy(vm, &pq);
+ ret = njs_prop_private_copy(vm, &pq);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.h
--- a/njs/njs_object.h Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_object.h Tue Jun 04 19:38:50 2019 +0300
@@ -115,7 +115,7 @@ njs_value_t *njs_property_constructor_cr
njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
-njs_ret_t njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq);
+njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq);
const char * njs_prop_type_string(njs_object_property_type_t type);
extern const njs_object_init_t njs_object_constructor_init;
diff -r deef19f6498a -r 8b27db801cd3 njs/njs_vm.c
--- a/njs/njs_vm.c Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_vm.c Tue Jun 04 19:38:50 2019 +0300
@@ -3069,7 +3069,7 @@ njs_value_property(njs_vm_t *vm, const n
case NJS_METHOD:
if (pq.shared) {
- ret = njs_method_private_copy(vm, &pq);
+ ret = njs_prop_private_copy(vm, &pq);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
diff -r deef19f6498a -r 8b27db801cd3 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/test/njs_unit_test.c Tue Jun 04 19:38:50 2019 +0300
@@ -9320,6 +9320,18 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("var o = {}; Object.defineProperty(o)"),
nxt_string("TypeError: descriptor is not an object") },
+ { nxt_string("Object.defineProperty(Function.prototype, 'name', {value:'x'}).name"),
+ nxt_string("x") },
+
+ { nxt_string("Object.defineProperty(Function.prototype, 'xxx', {value:'x'}).xxx"),
+ nxt_string("x") },
+
+ { nxt_string("Object.defineProperty(Object, 'name', {value:'x'}).name"),
+ nxt_string("x") },
+
+ { nxt_string("Object.defineProperty(Object.prototype, 'toString', {value:1}).toString"),
+ nxt_string("1") },
+
{ nxt_string("var o = Object.defineProperties({}, {a:{value:1}}); o.a"),
nxt_string("1") },
More information about the nginx-devel
mailing list