]> git.kaiwu.me - njs.git/commitdiff
Fix Array.prototype.concat() with sparse arrays
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 4 Sep 2026 01:47:58 +0000 (18:47 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Fri, 4 Sep 2026 21:53:08 +0000 (14:53 -0700)
Previously, the fast concat path represented a missing source property with
njs_value_invalid and still created the corresponding destination property.
For a slow sparse destination this materialized an internal hole sentinel as
a normal property, which later property access could interpret as an invalid
accessor.

The fix is to advance the destination index without creating a property when
the source lookup reports a hole.

The issue was introduced in 232fb594 (0.7.2).

This closes #1095 issue on GitHub.

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

index 5c30e833d9413b7338779f5cee0e6b12a231a28b..a9ea5143f9def4e09016e0ffb914f827eb1fdaab 100644 (file)
@@ -1961,7 +1961,7 @@ njs_array_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
                             return NJS_ERROR;
                         }
 
-                        njs_set_invalid(&value);
+                        continue;
                     }
 
                     ret = njs_value_property_i64_set(vm, &this, length,
index 8ce6c53f28b87ff7b2e89de75a19ab4a29331300..3fc8690881491de4b710d21d8e2d7b4edbe22237 100644 (file)
@@ -5193,6 +5193,11 @@ static njs_unit_test_t  njs_test[] =
               "njs.dump(a2)"),
       njs_str("[3,1,<1111110 empty items>,2,4]") },
 
+    { njs_str("var a = []; a[100000] = 1;"
+              "var b = [].concat(a, [,, 5]);"
+              "[b.length, Object.keys(b), b[100001], b.sort().length]"),
+      njs_str("100004,100000,100003,,100004") },
+
     { njs_str("var re = /abc/; re[Symbol.isConcatSpreadable] = true;"
               "re[0] = 1, re[1] = 2, re[2] = 3, re.length = 3;"
               "[].concat(re)"),