From: Dmitry Volyntsev Date: Tue, 4 Jun 2019 16:38:50 +0000 (+0300) Subject: Fixed Object.defineProperty() for shared descriptors. X-Git-Tag: 0.3.3~16 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=4b6383746933e13353379df0e4639130324bcaec;p=njs.git Fixed Object.defineProperty() for shared descriptors. This closes #172 issue on Github. --- diff --git a/njs/njs_object.c b/njs/njs_object.c index cb3d1d4a..fad29332 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -708,7 +708,7 @@ njs_external_property_delete(njs_vm_t *vm, njs_value_t *value, 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, njs_property_query_t *pq) 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, njs_property_query_t *pq) 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_value_t *object, const njs_value_t *name, /* 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 *vm, njs_value_t *dest, 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 --git a/njs/njs_object.h b/njs/njs_object.h index ad7780fa..25e1d737 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -115,7 +115,7 @@ njs_value_t *njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, 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 --git a/njs/njs_vm.c b/njs/njs_vm.c index f7ba55c9..74886178 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -3069,7 +3069,7 @@ njs_value_property(njs_vm_t *vm, const njs_value_t *value, 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 --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index e400ad52..07c2ae71 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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") },