[njs] Introduced njs_array_copy_within().

Dmitry Volyntsev xeioex at nginx.com
Wed Jun 3 18:41:12 UTC 2020


details:   https://hg.nginx.org/njs/rev/a23651137ccf
branches:  
changeset: 1421:a23651137ccf
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Jun 03 18:40:09 2020 +0000
description:
Introduced njs_array_copy_within().

diffstat:

 src/njs_array.c          |  105 +++++++++++++++++++++++++---------------------
 src/test/njs_unit_test.c |    7 +++
 2 files changed, 64 insertions(+), 48 deletions(-)

diffs (157 lines):

diff -r 61dce54ce3d5 -r a23651137ccf src/njs_array.c
--- a/src/njs_array.c	Wed Jun 03 20:49:52 2020 +0300
+++ b/src/njs_array.c	Wed Jun 03 18:40:09 2020 +0000
@@ -250,6 +250,60 @@ done:
 }
 
 
+static njs_int_t
+njs_array_copy_within(njs_vm_t *vm, njs_value_t *array, int64_t to_pos,
+    int64_t from_pos, int64_t count, njs_bool_t forward)
+{
+    int64_t      i, from, to;
+    njs_int_t    ret;
+    njs_array_t  *arr;
+    njs_value_t  value;
+
+    if (njs_fast_path(njs_is_fast_array(array) && count > 0)) {
+        arr = njs_array(array);
+
+        memmove(&arr->start[to_pos], &arr->start[from_pos],
+                count * sizeof(njs_value_t));
+
+        return NJS_OK;
+    }
+
+    if (!forward) {
+        from_pos += count - 1;
+        to_pos += count - 1;
+    }
+
+    for (i = 0; i < count; i++) {
+        if (forward) {
+            from = from_pos + i;
+            to = to_pos + i;
+
+        } else {
+            from = from_pos - i;
+            to = to_pos - i;
+        }
+
+        ret = njs_value_property_i64(vm, array, from, &value);
+        if (njs_slow_path(ret == NJS_ERROR)) {
+            return NJS_ERROR;
+        }
+
+        if (ret == NJS_OK) {
+            ret = njs_value_property_i64_set(vm, array, to, &value);
+
+        } else {
+            ret = njs_value_property_i64_delete(vm, array, to, NULL);
+        }
+
+        if (njs_slow_path(ret == NJS_ERROR)) {
+            return NJS_ERROR;
+        }
+    }
+
+    return NJS_OK;
+}
+
+
 njs_int_t
 njs_array_add(njs_vm_t *vm, njs_array_t *array, njs_value_t *value)
 {
@@ -3423,11 +3477,9 @@ static njs_int_t
 njs_array_prototype_copy_within(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused)
 {
-    int8_t       direction;
     int64_t      length, count, to, from, end;
     njs_int_t    ret;
-    njs_array_t  *array;
-    njs_value_t  *this, *value, prop;
+    njs_value_t  *this, *value;
 
     this = njs_argument(args, 0);
 
@@ -3471,53 +3523,10 @@ njs_array_prototype_copy_within(njs_vm_t
 
     count = njs_min(end - from, length - to);
 
-    if (from < to && from + count) {
-        direction = -1;
-        from = from + count - 1;
-        to = to + count - 1;
-
-    } else {
-        direction = 1;
-    }
-
     njs_vm_retval_set(vm, this);
 
-    if (njs_fast_path(njs_is_fast_array(this))) {
-        array = njs_array(this);
-
-        while (count-- > 0) {
-            array->start[to] = array->start[from];
-
-            from = from + direction;
-            to = to + direction;
-        }
-
-        return NJS_OK;
-    }
-
-    while (count-- > 0) {
-        ret = njs_value_property_i64(vm, this, from, &prop);
-
-        if (ret == NJS_OK) {
-            ret = njs_value_property_i64_set(vm, this, to, &prop);
-
-        } else {
-            if (njs_slow_path(ret == NJS_ERROR)) {
-                return ret;
-            }
-
-            ret = njs_value_property_i64_delete(vm, this, to, NULL);
-        }
-
-        if (njs_slow_path(ret == NJS_ERROR)) {
-            return ret;
-        }
-
-        from = from + direction;
-        to = to + direction;
-    }
-
-    return NJS_OK;
+    return njs_array_copy_within(vm, this, to, from, count,
+                                 !(from < to && to < from + count));
 }
 
 
diff -r 61dce54ce3d5 -r a23651137ccf src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Jun 03 20:49:52 2020 +0300
+++ b/src/test/njs_unit_test.c	Wed Jun 03 18:40:09 2020 +0000
@@ -4165,6 +4165,9 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("[0, 1, , , 1].copyWithin(0, 1, 4)"),
       njs_str("1,,,,1") },
 
+    { njs_str("[0, 1, 2, 3].copyWithin(0, 1, -10)"),
+      njs_str("0,1,2,3") },
+
     { njs_str("var o = [0, 1, , , 1].copyWithin(0, 1, 4); typeof o"),
       njs_str("object") },
 
@@ -4184,6 +4187,10 @@ static njs_unit_test_t  njs_test[] =
               "Object.keys(obj) + '|' + Object.values(obj)"),
       njs_str("length,1,2,3,4,5,0|5,a,b,c,d,e,c") },
 
+    { njs_str("var o = {length:1}; Object.defineProperty(o, '0', {get:()=>{throw Error('Oops')}});"
+              "Array.prototype.copyWithin.call(o, 0, 0)"),
+      njs_str("Error: Oops") },
+
     { njs_str("Array.prototype.slice(1)"),
       njs_str("") },
 


More information about the nginx-devel mailing list