From 15099bc8fec5bfa76f43c14220f88d6115e63376 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 19 Oct 2018 20:54:59 +0300 Subject: [PATCH] delete operator refactored. --- njs/njs_json.c | 9 ++++++++- njs/njs_object.c | 4 ++-- njs/njs_vm.c | 23 +++++++++++++++++------ njs/test/njs_unit_test.c | 22 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/njs/njs_json.c b/njs/njs_json.c index bdd6b3b0..340e03e2 100644 --- a/njs/njs_json.c +++ b/njs/njs_json.c @@ -934,6 +934,12 @@ njs_json_parse_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, } prop = lhq.value; + + if (prop->type == NJS_WHITEOUT) { + state->index++; + break; + } + state->prop_value = &prop->value; if (njs_json_is_non_empty(&prop->value)) { @@ -1233,6 +1239,7 @@ njs_json_stringify_continuation(njs_vm_t *vm, njs_value_t *args, if (!prop->enumerable || njs_is_void(&prop->value) + || !njs_is_valid(&prop->value) || njs_is_function(&prop->value)) { break; @@ -2382,7 +2389,7 @@ njs_vm_value_dump(njs_vm_t *vm, nxt_str_t *retval, const njs_value_t *value, prop = lhq.value; val = &prop->value; - if (!prop->enumerable) { + if (prop->type == NJS_WHITEOUT || !prop->enumerable) { break; } } diff --git a/njs/njs_object.c b/njs/njs_object.c index bdc13076..4872650b 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -922,7 +922,7 @@ njs_object_keys_array(njs_vm_t *vm, const njs_value_t *object) break; } - if (prop->enumerable) { + if (prop->type != NJS_WHITEOUT && prop->enumerable) { keys_length++; } } @@ -954,7 +954,7 @@ njs_object_keys_array(njs_vm_t *vm, const njs_value_t *object) break; } - if (prop->enumerable) { + if (prop->type != NJS_WHITEOUT && prop->enumerable) { njs_string_copy(&keys->start[n++], &prop->name); } } diff --git a/njs/njs_vm.c b/njs/njs_vm.c index e10ed68c..a2a1884f 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -552,6 +552,19 @@ njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object, return NXT_ERROR; } + if (nxt_slow_path(pq.lhq.value != NULL)) { + prop = pq.lhq.value; + + if (nxt_slow_path(prop->type == NJS_WHITEOUT)) { + /* Previously deleted property. */ + prop->type = NJS_PROPERTY; + prop->enumerable = 1; + prop->configurable = 1; + prop->writable = 1; + break; + } + } + prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_void, 1); if (nxt_slow_path(prop == NULL)) { return NXT_ERROR; @@ -695,11 +708,9 @@ njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *object, return NXT_ERROR; } - pq.lhq.pool = vm->mem_cache_pool; - - (void) nxt_lvlhsh_delete(&object->data.u.object->hash, &pq.lhq); - - njs_release(vm, property); + /* GC: release value. */ + prop->type = NJS_WHITEOUT; + njs_set_invalid(&prop->value); retval = &njs_value_true; @@ -811,7 +822,7 @@ njs_vmcode_property_next(njs_vm_t *vm, njs_value_t *object, njs_value_t *value) break; } - if (prop->enumerable) { + if (prop->type != NJS_WHITEOUT && prop->enumerable) { *retval = prop->name; return code->offset; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 8bec27ca..db134ff0 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -2112,6 +2112,14 @@ static njs_unit_test_t njs_test[] = "for (var p in o) {s += p}; s"), nxt_string("y") }, + { nxt_string("var o = {a:1, b:2}; var arr = []; " + "for (var a in o) {arr.push(a)}; arr"), + nxt_string("a,b") }, + + { nxt_string("var o = {a:1, b:2}; var arr = []; delete o.a; " + "for (var a in o) {arr.push(a)}; arr"), + nxt_string("b") }, + /* switch. */ { nxt_string("switch"), @@ -2636,6 +2644,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("delete --[][1]"), nxt_string("true") }, + { nxt_string("var a = [1,2]; delete a.length"), + nxt_string("false") }, + { nxt_string("var a = [1,2,3]; a.x = 10; delete a[1]"), nxt_string("true") }, @@ -2654,6 +2665,14 @@ static njs_unit_test_t njs_test[] = { nxt_string("Math.E = 1"), nxt_string("TypeError: Cannot assign to read-only property 'E' of object") }, + { nxt_string("var o = { 'a': 1, 'b': 2 }; var i; " + "for (i in o) { delete o.a; delete o.b; }; njs.dump(o)"), + nxt_string("{}") }, + + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {value:1, configurable:1}); " + "delete o.a; o.a=2; o.a"), + nxt_string("2") }, + { nxt_string("var a = {}; 1 in a"), nxt_string("false") }, @@ -6894,6 +6913,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var a = [,6,,3]; a.one = 7; Object.keys(a)"), nxt_string("1,3,one") }, + { nxt_string("var o = {a:1,b:2}; delete o.a; Object.keys(o)"), + nxt_string("b") }, + { nxt_string("Object.keys()"), nxt_string("TypeError: cannot convert void argument to object") }, -- 2.47.3