]> git.kaiwu.me - njs.git/commitdiff
Simplified element access in Array.prototype.shift().
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 13 Jan 2022 18:30:31 +0000 (18:30 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 13 Jan 2022 18:30:31 +0000 (18:30 +0000)
Previously, array structure may be left in inconsistent state
when a custom getter in a proto array changes array size.

The change is similar to the previous commits.

src/njs_array.c

index 0f0854b5d43f3251fdaa702f89ae8ba9c9806828..112f9152edf8b80e597a9ad4c5fbbabb752e0f4b 100644 (file)
@@ -1135,78 +1135,67 @@ njs_array_prototype_shift(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     int64_t      i, length;
     njs_int_t    ret;
     njs_array_t  *array;
-    njs_value_t  *this, *item, entry;
+    njs_value_t  *this, entry;
 
     this = njs_argument(args, 0);
-    length = 0;
 
     ret = njs_value_to_object(vm, this);
     if (njs_slow_path(ret != NJS_OK)) {
         return ret;
     }
 
-    njs_set_undefined(&vm->retval);
-
-    if (njs_is_fast_array(this)) {
-        array = njs_array(this);
-
-        if (array->length != 0) {
-            array->length--;
-            item = &array->start[0];
-
-            if (njs_is_valid(item)) {
-                vm->retval = *item;
-
-            } else {
-                /* src value may be in Array.prototype object. */
-
-                ret = njs_value_property_i64(vm, this, 0, &vm->retval);
-                if (njs_slow_path(ret == NJS_ERROR)) {
-                    return NJS_ERROR;
-                }
-            }
-
-            array->start++;
-        }
-
-        return NJS_OK;
-    }
-
     ret = njs_object_length(vm, this, &length);
     if (njs_slow_path(ret == NJS_ERROR)) {
         return ret;
     }
 
     if (length == 0) {
-        goto done;
+        ret = njs_object_length_set(vm, this, length);
+        if (njs_slow_path(ret == NJS_ERROR)) {
+            return ret;
+        }
+
+        njs_set_undefined(&vm->retval);
+
+        return NJS_OK;
     }
 
-    ret = njs_value_property_i64_delete(vm, this, 0, &vm->retval);
+    ret = njs_value_property_i64(vm, this, 0, &vm->retval);
     if (njs_slow_path(ret == NJS_ERROR)) {
-        return ret;
+        return NJS_ERROR;
     }
 
-    for (i = 1; i < length; i++) {
-        ret = njs_value_property_i64_delete(vm, this, i, &entry);
+    if (njs_is_fast_array(this)) {
+        array = njs_array(this);
+
+        array->start++;
+        array->length--;
+
+    } else {
+
+        ret = njs_value_property_i64_delete(vm, this, 0, &vm->retval);
         if (njs_slow_path(ret == NJS_ERROR)) {
             return ret;
         }
 
-        if (ret == NJS_OK) {
-            ret = njs_value_property_i64_set(vm, this, i - 1, &entry);
+        for (i = 1; i < length; i++) {
+            ret = njs_value_property_i64_delete(vm, this, i, &entry);
             if (njs_slow_path(ret == NJS_ERROR)) {
                 return ret;
             }
-        }
-    }
-
-    length--;
 
-done:
+            if (ret == NJS_OK) {
+                ret = njs_value_property_i64_set(vm, this, i - 1, &entry);
+                if (njs_slow_path(ret == NJS_ERROR)) {
+                    return ret;
+                }
+            }
+        }
 
-    ret = njs_object_length_set(vm, this, length);
-    if (njs_slow_path(ret == NJS_ERROR)) {
-        return ret;
+        ret = njs_object_length_set(vm, this, length - 1);
+        if (njs_slow_path(ret == NJS_ERROR)) {
+            return ret;
+        }
     }
 
     return NJS_OK;