]> git.kaiwu.me - njs.git/commitdiff
Fixed Array.prototype.concat() when "this" is a slow array.
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 21 Feb 2022 16:52:47 +0000 (16:52 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 21 Feb 2022 16:52:47 +0000 (16:52 +0000)
Previously, when the current appended element is fast array the "this"
array was expected to always be a fast array also.  This may not be the
case when the previous appended element was not fast thus converting
the "this" array to a slow form.

Previous fix introduced in 2c1382bab643 (0.7.2) was not complete, the
correct fix is to never assume "this" is fast, whereas njs_array_add()
may only be called with fast arrays.

This closes #471 issue in Github.

src/njs_array.c
src/test/njs_unit_test.c

index 7e81d6c6a03556b92d44f0d228a7f7980793c790..81a7c15550efb99e93f89b329ad18a1e32c1f3f4 100644 (file)
@@ -364,6 +364,8 @@ njs_array_expand(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
     uint64_t     size;
     njs_value_t  *start, *old;
 
+    njs_assert(array->object.fast_array);
+
     free_before = array->start - array->data;
     free_after = array->size - array->length - free_before;
 
@@ -1754,9 +1756,10 @@ njs_array_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
                         njs_set_invalid(&retval);
                     }
 
-                    ret = njs_array_add(vm, array, &retval);
-                    if (njs_slow_path(ret != NJS_OK)) {
-                        return NJS_ERROR;
+                    ret = njs_value_property_i64_set(vm, &this, length,
+                                                     &retval);
+                    if (njs_slow_path(ret == NJS_ERROR)) {
+                        return ret;
                     }
                 }
 
index 89bc1615493045d1693b91bffc3fbc000663262a..dc18a13b132bb161731131b554cddfb9b7f6202d 100644 (file)
@@ -4253,6 +4253,11 @@ static njs_unit_test_t  njs_test[] =
               "njs.dump([a[0], a[33],a.length])"),
       njs_str("[1,1,65]") },
 
+    { njs_str("var a = [1]; a[1111111] = 2;"
+              "var a2 = [3].concat(a, [4]);"
+              "njs.dump(a2)"),
+      njs_str("[3,1,<1111110 empty items>,2,4]") },
+
     { njs_str("var re = /abc/; re[Symbol.isConcatSpreadable] = true;"
               "re[0] = 1, re[1] = 2, re[2] = 3, re.length = 3;"
               "[].concat(re)"),