[njs] Simplified element access in Array.prototype.shift().

Dmitry Volyntsev xeioex at nginx.com
Fri Jan 14 14:57:27 UTC 2022


details:   https://hg.nginx.org/njs/rev/dfbde7620ced
branches:  
changeset: 1806:dfbde7620ced
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jan 13 18:30:31 2022 +0000
description:
Simplified element access in Array.prototype.shift().

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.

diffstat:

 src/njs_array.c |  89 ++++++++++++++++++++++++--------------------------------
 1 files changed, 39 insertions(+), 50 deletions(-)

diffs (121 lines):

diff -r 762774041f05 -r dfbde7620ced src/njs_array.c
--- a/src/njs_array.c	Thu Jan 13 18:30:31 2022 +0000
+++ b/src/njs_array.c	Thu Jan 13 18:30:31 2022 +0000
@@ -1135,78 +1135,67 @@ njs_array_prototype_shift(njs_vm_t *vm, 
     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_value_property_i64_delete(vm, this, 0, &vm->retval);
-    if (njs_slow_path(ret == NJS_ERROR)) {
-        return ret;
-    }
-
-    for (i = 1; i < length; i++) {
-        ret = njs_value_property_i64_delete(vm, this, i, &entry);
+        ret = njs_object_length_set(vm, this, length);
         if (njs_slow_path(ret == NJS_ERROR)) {
             return ret;
         }
 
-        if (ret == NJS_OK) {
-            ret = njs_value_property_i64_set(vm, this, i - 1, &entry);
+        njs_set_undefined(&vm->retval);
+
+        return NJS_OK;
+    }
+
+    ret = njs_value_property_i64(vm, this, 0, &vm->retval);
+    if (njs_slow_path(ret == NJS_ERROR)) {
+        return NJS_ERROR;
+    }
+
+    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;
+        }
+
+        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;
             }
+
+            if (ret == NJS_OK) {
+                ret = njs_value_property_i64_set(vm, this, i - 1, &entry);
+                if (njs_slow_path(ret == NJS_ERROR)) {
+                    return ret;
+                }
+            }
         }
-    }
-
-    length--;
-
-done:
-
-    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;



More information about the nginx-devel mailing list