[njs] Fixed Array.prototype.sort() when array is changed while sorting.
Dmitry Volyntsev
xeioex at nginx.com
Sat Mar 4 02:50:10 UTC 2023
details: https://hg.nginx.org/njs/rev/7ad9dd5da3fb
branches:
changeset: 2063:7ad9dd5da3fb
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Mar 03 17:49:11 2023 -0800
description:
Fixed Array.prototype.sort() when array is changed while sorting.
Previously, the fast-path check did not take into account the fact that
the flat array may be resized as a side effect of the array's values
evaluation.
In addition, the slow_path fix ensures that "this" array is repopulated
again even if the array was resized.
This fixes #594 issue on Github.
diffstat:
src/njs_array.c | 13 +++++++------
src/test/njs_unit_test.c | 28 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 6 deletions(-)
diffs (68 lines):
diff -r 163229f0c552 -r 7ad9dd5da3fb src/njs_array.c
--- a/src/njs_array.c Fri Mar 03 17:49:10 2023 -0800
+++ b/src/njs_array.c Fri Mar 03 17:49:11 2023 -0800
@@ -2663,7 +2663,10 @@ slow_path:
goto exception;
}
- if (njs_fast_path(fast_path && njs_is_fast_array(this))) {
+ if (njs_fast_path(fast_path
+ && njs_is_fast_array(this)
+ && (njs_array(this)->length == length)))
+ {
array = njs_array(this);
start = array->start;
@@ -2677,11 +2680,9 @@ slow_path:
} else {
for (i = 0; i < len; i++) {
- if (slots[i].pos != i) {
- ret = njs_value_property_i64_set(vm, this, i, &slots[i].value);
- if (njs_slow_path(ret == NJS_ERROR)) {
- goto exception;
- }
+ ret = njs_value_property_i64_set(vm, this, i, &slots[i].value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ goto exception;
}
}
diff -r 163229f0c552 -r 7ad9dd5da3fb src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Fri Mar 03 17:49:10 2023 -0800
+++ b/src/test/njs_unit_test.c Fri Mar 03 17:49:11 2023 -0800
@@ -7276,6 +7276,34 @@ static njs_unit_test_t njs_test[] =
{ njs_str("var a = [1,2]; a.sort(() => {a.length = 65535}); a.length"),
njs_str("65535") },
+ { njs_str("var a = [];"
+ "var shift = true;"
+ "for (let i = 0; i < 64; i++) {"
+ " a[i] = { toString() {"
+ " if (shift) { a.shift() };"
+ " return (63 - i).toString().padStart(2, '0');"
+ " }"
+ " };"
+ "}"
+ "a.sort();"
+ "shift = false;"
+ "[a.length, a[0].toString(), a[63].toString()]"),
+ njs_str("64,00,63") },
+
+ { njs_str("var a = [];"
+ "var shift = true;"
+ "for (let i = 0; i < 64; i++) {"
+ " a[i] = { toString() {"
+ " if (shift) { a.shift() };"
+ " return (i).toString().padStart(2, '0');"
+ " }"
+ " };"
+ "}"
+ "a.sort();"
+ "shift = false;"
+ "[a.length, a[0].toString(), a[63].toString()]"),
+ njs_str("64,00,63") },
+
/*
Array.prototype.keys()
Array.prototype.values()
More information about the nginx-devel
mailing list