]> git.kaiwu.me - njs.git/commitdiff
delete operator refactored.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 19 Oct 2018 17:54:59 +0000 (20:54 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 19 Oct 2018 17:54:59 +0000 (20:54 +0300)
njs/njs_json.c
njs/njs_object.c
njs/njs_vm.c
njs/test/njs_unit_test.c

index bdd6b3b0486dc1f00b6734af342c52b00e319f34..340e03e274ff545da7e953ba03febfc6efd2ea2f 100644 (file)
@@ -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;
                 }
             }
index bdc13076807ff621eac30b3df4cf48adc80b2c3d..4872650b07f8ec7629b218eec3c754ef59f9a68f 100644 (file)
@@ -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);
         }
     }
index e10ed68c9de1ca21bb2a1be4280c7672b543402a..a2a1884f3544155e80d0b7c94e4526724dcf9dfa 100644 (file)
@@ -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;
index 8bec27ca8a605a06ebd92d24b4fec4a3e826815d..db134ff0a635a6a70c69fde37426ff38262a3f41 100644 (file)
@@ -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") },