diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java index 86fbad6b19..d0276715d7 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java @@ -334,6 +334,22 @@ protected void initPrototypeId(int id) { arity = 1; s = "flatMap"; break; + case Id_toReversed: + arity = 0; + s = "toReversed"; + break; + case Id_toSorted: + arity = 1; + s = "toSorted"; + break; + case Id_toSpliced: + arity = 2; + s = "toSpliced"; + break; + case Id_with: + arity = 2; + s = "with"; + break; default: throw new IllegalArgumentException(String.valueOf(id)); } @@ -532,6 +548,15 @@ public Object execIdCall( thisObj = ScriptRuntime.toObject(cx, scope, thisObj); return new NativeArrayIterator( scope, thisObj, NativeArrayIterator.ARRAY_ITERATOR_TYPE.VALUES); + + case Id_toReversed: + return js_toReversed(cx, scope, thisObj, args); + case Id_toSorted: + return js_toSorted(cx, scope, thisObj, args); + case Id_toSpliced: + return js_toSpliced(cx, scope, thisObj, args); + case Id_with: + return js_with(cx, scope, thisObj, args); } throw new IllegalArgumentException( "Array.prototype has no method: " + f.getFunctionName()); @@ -1350,10 +1375,12 @@ private static Scriptable js_sort( final Scriptable thisObj, final Object[] args) { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - - final Comparator comparator = + Comparator comparator = ArrayLikeAbstractOperations.getSortComparator(cx, scope, args); + return sort(cx, o, comparator); + } + private static Scriptable sort(Context cx, Scriptable o, Comparator comparator) { long llength = getLengthProperty(cx, o); final int length = (int) llength; if (llength != length) { @@ -2174,6 +2201,136 @@ private static boolean js_isArray(Object o) { return "Array".equals(((Scriptable) o).getClassName()); } + private static Object js_toSorted( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + Comparator comparator = + ArrayLikeAbstractOperations.getSortComparator(cx, scope, args); + + Scriptable source = ScriptRuntime.toObject(cx, scope, thisObj); + long len = getLengthProperty(cx, source); + + if (len > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + Scriptable result = cx.newArray(scope, (int) len); + + for (int k = 0; k < len; ++k) { + Object fromValue = getElem(cx, source, k); + setElem(cx, result, k, fromValue); + } + + sort(cx, result, comparator); + return result; + } + + private static Object js_toReversed( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + Scriptable source = ScriptRuntime.toObject(cx, scope, thisObj); + long len = getLengthProperty(cx, source); + + if (len > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + Scriptable result = cx.newArray(scope, (int) len); + + for (int k = 0; k < len; ++k) { + int from = (int) len - k - 1; + Object fromValue = getElem(cx, source, from); + setElem(cx, result, k, fromValue); + } + + return result; + } + + private static Object js_toSpliced( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + Scriptable source = ScriptRuntime.toObject(cx, scope, thisObj); + long len = getLengthProperty(cx, source); + + long actualStart = 0; + if (args.length > 0) { + actualStart = + ArrayLikeAbstractOperations.toSliceIndex(ScriptRuntime.toInteger(args[0]), len); + } + + long insertCount = args.length > 2 ? args.length - 2 : 0; + + long actualSkipCount; + if (args.length == 0) { + actualSkipCount = 0; + } else if (args.length == 1) { + actualSkipCount = len - actualStart; + } else { + long sc = ScriptRuntime.toLength(args, 1); + actualSkipCount = Math.max(0, Math.min(sc, len - actualStart)); + } + + long newLen = len + insertCount - actualSkipCount; + if (newLen > NativeNumber.MAX_SAFE_INTEGER) { + throw ScriptRuntime.typeErrorById("msg.arraylength.too.big", newLen); + } + if (newLen > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + + Scriptable result = cx.newArray(scope, (int) newLen); + + long i = 0; + long r = actualStart + actualSkipCount; + + while (i < actualStart) { + Object e = getElem(cx, source, i); + setElem(cx, result, i, e); + i++; + } + + for (int j = 2; j < args.length; j++) { + setElem(cx, result, i, args[j]); + i++; + } + + while (i < newLen) { + Object e = getElem(cx, source, r); + setElem(cx, result, i, e); + i++; + r++; + } + + return result; + } + + private static Object js_with(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + Scriptable source = ScriptRuntime.toObject(cx, scope, thisObj); + + long len = getLengthProperty(cx, source); + long relativeIndex = args.length > 0 ? (int) ScriptRuntime.toInteger(args[0]) : 0; + long actualIndex = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; + + if (actualIndex < 0 || actualIndex >= len) { + throw ScriptRuntime.rangeError("index out of range"); + } + if (len > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + + Scriptable result = cx.newArray(scope, (int) len); + for (long k = 0; k < len; ++k) { + Object value; + if (k == actualIndex) { + value = args.length > 1 ? args[1] : Undefined.instance; + } else { + value = getElem(cx, source, k); + } + setElem(cx, result, k, value); + } + + return result; + } + // methods to implement java.util.List @Override @@ -2563,6 +2720,18 @@ protected int findPrototypeId(String s) { case "flatMap": id = Id_flatMap; break; + case "toReversed": + id = Id_toReversed; + break; + case "toSorted": + id = Id_toSorted; + break; + case "toSpliced": + id = Id_toSpliced; + break; + case "with": + id = Id_with; + break; default: id = 0; break; @@ -2606,7 +2775,11 @@ protected int findPrototypeId(String s) { Id_at = 34, Id_flat = 35, Id_flatMap = 36, - SymbolId_unscopables = 37, + Id_toReversed = 37, + Id_toSorted = 38, + Id_toSpliced = 39, + Id_with = 40, + SymbolId_unscopables = 41, MAX_PROTOTYPE_ID = SymbolId_unscopables; private static final int ConstructorId_join = -Id_join, ConstructorId_reverse = -Id_reverse, diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java index efc4990030..b4feb33dee 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java @@ -518,6 +518,15 @@ private NativeTypedArrayView js_fill(Object[] args) { } private Scriptable js_sort(Context cx, Scriptable scope, Object[] args) { + Object[] working = sortTemporaryArray(cx, scope, args); + for (int i = 0; i < length; ++i) { + js_set(i, working[i]); + } + + return this; + } + + private Object[] sortTemporaryArray(Context cx, Scriptable scope, Object[] args) { Comparator comparator; if (args.length > 0 && Undefined.instance != args[0]) { comparator = ArrayLikeAbstractOperations.getSortComparator(cx, scope, args); @@ -528,12 +537,7 @@ private Scriptable js_sort(Context cx, Scriptable scope, Object[] args) { // Temporary array to rely on Java's built-in sort, which is stable. Object[] working = toArray(); Arrays.sort(working, comparator); - - for (int i = 0; i < length; ++i) { - js_set(i, working[i]); - } - - return this; + return working; } private Object js_copyWithin(Object[] args) { @@ -628,6 +632,65 @@ private Scriptable typedArraySpeciesCreate( return newArray; } + private Object js_toReversed(Context cx, Scriptable scope) { + NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + Scriptable result = + cx.newObject( + scope, + getClassName(), + new Object[] {newBuffer, 0, length, getBytesPerElement()}); + + for (int k = 0; k < length; ++k) { + int from = length - k - 1; + Object fromValue = js_get(from); + result.put(k, result, fromValue); + } + + return result; + } + + private Object js_toSorted(Context cx, Scriptable scope, Object[] args) { + Object[] working = sortTemporaryArray(cx, scope, args); + + // Move value in a new typed array of the same type + NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + Scriptable result = + cx.newObject( + scope, + getClassName(), + new Object[] {newBuffer, 0, length, getBytesPerElement()}); + for (int k = 0; k < length; ++k) { + result.put(k, result, working[k]); + } + + return result; + } + + private Object js_with(Context cx, Scriptable scope, Object[] args) { + long relativeIndex = args.length > 0 ? (int) ScriptRuntime.toInteger(args[0]) : 0; + long actualIndex = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; + + Object argsValue = args.length > 1 ? ScriptRuntime.toNumber(args[1]) : 0.0; + + if (actualIndex < 0 || actualIndex >= length) { + throw ScriptRuntime.rangeError("index out of range"); + } + + NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + Scriptable result = + cx.newObject( + scope, + getClassName(), + new Object[] {newBuffer, 0, length, getBytesPerElement()}); + + for (int k = 0; k < length; ++k) { + Object fromValue = (k == actualIndex) ? argsValue : js_get(k); + result.put(k, result, fromValue); + } + + return result; + } + // Dispatcher @Override @@ -783,6 +846,12 @@ public Object execIdCall( case Id_reduceRight: return ArrayLikeAbstractOperations.reduceMethod( cx, ReduceOperation.REDUCE_RIGHT, scope, thisObj, args); + case Id_toReversed: + return realThis(thisObj, f).js_toReversed(cx, scope); + case Id_toSorted: + return realThis(thisObj, f).js_toSorted(cx, scope, args); + case Id_with: + return realThis(thisObj, f).js_with(cx, scope, args); case SymbolId_iterator: return new NativeArrayIterator(scope, thisObj, ARRAY_ITERATOR_TYPE.VALUES); @@ -920,6 +989,18 @@ protected void initPrototypeId(int id) { arity = 1; s = "reduceRight"; break; + case Id_toSorted: + arity = 1; + s = "toSorted"; + break; + case Id_toReversed: + arity = 0; + s = "toReversed"; + break; + case Id_with: + arity = 2; + s = "with"; + break; default: throw new IllegalArgumentException(String.valueOf(id)); } @@ -1028,6 +1109,15 @@ protected int findPrototypeId(String s) { case "reduceRight": id = Id_reduceRight; break; + case "toSorted": + id = Id_toSorted; + break; + case "toReversed": + id = Id_toReversed; + break; + case "with": + id = Id_with; + break; default: id = 0; break; @@ -1066,7 +1156,10 @@ protected int findPrototypeId(String s) { Id_findLastIndex = 28, Id_reduce = 29, Id_reduceRight = 30, - SymbolId_iterator = 31; + Id_toReversed = 31, + Id_toSorted = 32, + Id_with = 33, + SymbolId_iterator = 34; protected static final int MAX_PROTOTYPE_ID = SymbolId_iterator; diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToReversedTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToReversedTest.java new file mode 100644 index 0000000000..729518031f --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToReversedTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/array-toReversed.js") +@LanguageVersion(Context.VERSION_ES6) +public class ArrayToReversedTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSortedTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSortedTest.java new file mode 100644 index 0000000000..f07e8718a5 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSortedTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/array-toSorted.js") +@LanguageVersion(Context.VERSION_ES6) +public class ArrayToSortedTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSplicedTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSplicedTest.java new file mode 100644 index 0000000000..da89cac0a2 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayToSplicedTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/array-toSpliced.js") +@LanguageVersion(Context.VERSION_ES6) +public class ArrayToSplicedTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayWithTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayWithTest.java new file mode 100644 index 0000000000..5196ea2081 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/ArrayWithTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/array-with.js") +@LanguageVersion(Context.VERSION_ES6) +public class ArrayWithTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToReversedTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToReversedTest.java new file mode 100644 index 0000000000..1061b8936e --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToReversedTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/typedArray-toReversed.js") +@LanguageVersion(Context.VERSION_ES6) +public class TypedArrayToReversedTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToSortedTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToSortedTest.java new file mode 100644 index 0000000000..0ea3d2ab71 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayToSortedTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/typedArray-toSorted.js") +@LanguageVersion(Context.VERSION_ES6) +public class TypedArrayToSortedTest extends ScriptTestsBase {} diff --git a/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayWithTest.java b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayWithTest.java new file mode 100644 index 0000000000..63a1663aa5 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/es2023/TypedArrayWithTest.java @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.tests.es2023; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.drivers.LanguageVersion; +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest("testsrc/jstests/es2023/typedArray-with.js") +@LanguageVersion(Context.VERSION_ES6) +public class TypedArrayWithTest extends ScriptTestsBase {} diff --git a/tests/testsrc/jstests/es2023/array-toReversed.js b/tests/testsrc/jstests/es2023/array-toReversed.js new file mode 100644 index 0000000000..28053cb6d2 --- /dev/null +++ b/tests/testsrc/jstests/es2023/array-toReversed.js @@ -0,0 +1,31 @@ +load("testsrc/assert.js"); + +(function toReversedBasic() { + var arr = [1, 2, 3]; + var reversed = arr.toReversed(); + + assertTrue(Array.isArray(reversed)); + assertEquals(3, reversed.length); + assertEquals("3,2,1", reversed.toString()); + + assertEquals(3, arr.length); + assertEquals("1,2,3", arr.toString()); +})(); + +(function toReversedArrayPreservesHoles() { + var arr = [0, /* hole */, 2, /* hole */, 4]; + Array.prototype[3] = 3; + var reversed = arr.toReversed(); + assertEquals("4,3,2,,0", reversed.toString()); + assertTrue(reversed.hasOwnProperty(3)); +})(); + +(function toReversedMaxLengthExceedingArrayLengthLimit() { + var arr = {length: 2**32}; + assertThrows( + () => Array.prototype.toReversed.call(arr, 0, 0), + RangeError + ); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/array-toSorted.js b/tests/testsrc/jstests/es2023/array-toSorted.js new file mode 100644 index 0000000000..555da08a87 --- /dev/null +++ b/tests/testsrc/jstests/es2023/array-toSorted.js @@ -0,0 +1,39 @@ +load("testsrc/assert.js"); + +(function toSortedBasic() { + var arr = [3, 1, 2, 4, 5, 6, 0, 7]; + var sorted = arr.toSorted(); + assertTrue(Array.isArray(sorted)); + assertEquals(8, sorted.length); + assertEquals("0,1,2,3,4,5,6,7", sorted.toString()); +})(); + +(function toSortedPassingComparatorFunction() { + var arr = [-1, -3, -2, -4, -1, -3, 0, 3, 1]; + var sorted = arr.toSorted((a, b) => b.toString().length - a.toString().length); + assertEquals("-1,-3,-2,-4,-1,-3,0,3,1", sorted.toString()); +})(); + +(function toSortedIsStable() { + var arr = [3, 1, 2, 4, 5, 6, 0, 7]; + var sorted = arr.toSorted((a, b) => a % 2 - b % 2); + assertEquals("2,4,6,0,3,1,5,7", sorted.toString()); +})(); + +(function toSortedMaxLengthExceedingArrayLengthLimit() { + var arr = {length: 2**32}; + assertThrows( + () => Array.prototype.toSorted.call(arr, (a, b) => b - a), + RangeError + ); +})(); + +(function toSortedComparatorIsNotFunction() { + var arr = [1, 2, 3] + assertThrows( + () => Array.prototype.toSorted.call(arr, 42), + TypeError + ); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/array-toSpliced.js b/tests/testsrc/jstests/es2023/array-toSpliced.js new file mode 100644 index 0000000000..69e55a44b0 --- /dev/null +++ b/tests/testsrc/jstests/es2023/array-toSpliced.js @@ -0,0 +1,61 @@ +load("testsrc/assert.js"); + +(function toSplicedNoArgument() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(); + assertTrue(Array.isArray(spliced)); + assertEquals(3, spliced.length); + assertEquals("1,2,3", spliced.toString()); +})(); + +(function toSplicedStart() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(2); + assertEquals("1,2", spliced.toString()); +})(); + +(function toSplicedNegativeStart() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(-1); + assertEquals("1,2", spliced.toString()); +})(); + +(function toSplicedStartUndefined() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(undefined); + assertEquals("", spliced.toString()); +})(); + +(function toSplicedStartAfterMaxLength() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(3); + assertEquals("1,2,3", spliced.toString()); +})(); + +(function toSplicedStartAndCount() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(0, 1); + assertEquals("2,3", spliced.toString()); +})(); + +(function toSplicedStartAndUndefinedCount() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(2, undefined); + assertEquals("1,2,3", spliced.toString()); +})(); + +(function toSplicedItemsToInsert() { + var arr = [1, 2, 3]; + var spliced = arr.toSpliced(0, 1, 4, 5); + assertEquals("4,5,2,3", spliced.toString()); +})(); + +(function toSplicedMaxLengthExceedingArrayLengthLimit() { + var arr = {length: 2**32}; + assertThrows( + () => Array.prototype.toSpliced.call(arr, 0, 0), + RangeError + ); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/array-with.js b/tests/testsrc/jstests/es2023/array-with.js new file mode 100644 index 0000000000..61a5ba9181 --- /dev/null +++ b/tests/testsrc/jstests/es2023/array-with.js @@ -0,0 +1,47 @@ +load("testsrc/assert.js"); + +(function withNoArgument() { + var arr = [1, 2, 3]; + var arrWith = arr.with(); + assertTrue(Array.isArray(arrWith)); + assertEquals(3, arrWith.length); + assertEquals(",2,3", arrWith.toString()); +})(); + +(function withIndex() { + var arr = [1, 2, 3]; + var arrWith = arr.with(1); + assertEquals("1,,3", arrWith.toString()); +})(); + +(function withIndexAndValue() { + var arr = [1, 2, 3]; + var arrWith = arr.with(1, 4); + assertEquals("1,4,3", arrWith.toString()); +})(); + +(function withNegativeIndexAndValue() { + var arr = [1, 2, 3]; + var arrWith = arr.with(-2, 5); + assertEquals("1,5,3", arrWith.toString()); +})(); + +(function withIndexTooLarge() { + var arr = [1, 2, 3]; + assertThrows(() => arr.with(3), RangeError); +})(); + +(function withIndexTooLarge() { + var arr = [1, 2, 3]; + assertThrows(() => arr.with(3), RangeError); +})(); + +(function withMaxLengthExceedingArrayLengthLimit() { + var arr = {length: 2**32}; + assertThrows( + () => Array.prototype.with.call(arr, 0, 0), + RangeError + ); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/typedArray-toReversed.js b/tests/testsrc/jstests/es2023/typedArray-toReversed.js new file mode 100644 index 0000000000..86ffc15374 --- /dev/null +++ b/tests/testsrc/jstests/es2023/typedArray-toReversed.js @@ -0,0 +1,30 @@ +load("testsrc/assert.js"); + +var types = [Int8Array, Uint8Array, Int16Array, Uint16Array, + Int32Array, Uint32Array, Uint8ClampedArray, Float32Array, + Float64Array]; + +(function toReversedBasic() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + + var reversed = arr.toReversed(); + assertFalse(arr === reversed); + assertSame(Object.getPrototypeOf(arr), Object.getPrototypeOf(reversed)); + assertEquals(3, reversed.length); + assertEquals("3,2,1", reversed.toString()); + } +})(); + +(function toReversedIgnoresSymbolSpecies() { + var ta = new Int8Array(); + ta.constructor = { + [Symbol.species]: Uint8Array, + }; + + var reversed = ta.toReversed(); + assertEquals(Object.getPrototypeOf(reversed), Int8Array.prototype); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/typedArray-toSorted.js b/tests/testsrc/jstests/es2023/typedArray-toSorted.js new file mode 100644 index 0000000000..6561304c7e --- /dev/null +++ b/tests/testsrc/jstests/es2023/typedArray-toSorted.js @@ -0,0 +1,56 @@ +load("testsrc/assert.js"); + +var types = [Int8Array, Uint8Array, Int16Array, Uint16Array, + Int32Array, Uint32Array, Uint8ClampedArray, Float32Array, + Float64Array]; + + +load("testsrc/assert.js"); + +var signedTypes = [Int8Array, Int16Array, Int32Array, Float32Array, Float64Array]; +var unsignedTypes = [Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray]; + +(function toSortedSigned() { + for (var t = 0; t < signedTypes.length; t++) { + var type = signedTypes[t]; + var arr = new type([3, -1, 2, -4, 5, -6, 0, 7]); + var sorted = arr.toSorted(); + assertEquals("3,-1,2,-4,5,-6,0,7", arr.toString()); + assertFalse(arr === sorted); + assertSame(Object.getPrototypeOf(arr), Object.getPrototypeOf(sorted)); + assertEquals("-6,-4,-1,0,2,3,5,7", sorted.toString()); + + // Check stability + arr = new type([-1, -3, -2, -4, -1, -3, 0, 3, 1]); + sorted = arr.toSorted((a, b) => b.toString().length - a.toString().length) + assertEquals("-1,-3,-2,-4,-1,-3,0,3,1", sorted.toString()); + } +})(); + +(function toSortedUnsigned() { + for (var t = 0; t < unsignedTypes.length; t++) { + var type = unsignedTypes[t]; + var arr = new type([3, 1, 2, 4, 5, 6, 0, 7]); + var sorted = arr.toSorted(); + assertEquals("3,1,2,4,5,6,0,7", arr.toString()); + assertFalse(arr === sorted); + assertSame(Object.getPrototypeOf(arr), Object.getPrototypeOf(sorted)); + assertEquals("0,1,2,3,4,5,6,7", sorted.toString()); + + // Check stability + sorted = arr.toSorted((a, b) => a % 2 - b % 2); + assertEquals("2,4,6,0,3,1,5,7", sorted.toString()); + } +})(); + +(function toSortedIgnoresSymbolSpecies() { + var ta = new Int8Array(); + ta.constructor = { + [Symbol.species]: Uint8Array, + }; + + var reversed = ta.toSorted(); + assertEquals(Object.getPrototypeOf(reversed), Int8Array.prototype); +})(); + +"success"; diff --git a/tests/testsrc/jstests/es2023/typedArray-with.js b/tests/testsrc/jstests/es2023/typedArray-with.js new file mode 100644 index 0000000000..f867dcd1ae --- /dev/null +++ b/tests/testsrc/jstests/es2023/typedArray-with.js @@ -0,0 +1,71 @@ +load("testsrc/assert.js"); + +var types = [Int8Array, Uint8Array, Int16Array, Uint16Array, + Int32Array, Uint32Array, Uint8ClampedArray, Float32Array, + Float64Array]; + + +load("testsrc/assert.js"); + +var types = [Int8Array, Uint8Array, Int16Array, Uint16Array, + Int32Array, Uint32Array, Uint8ClampedArray, Float32Array, + Float64Array]; + +(function withNoArguments() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + var res = arr.with(); + assertEquals("1,2,3", arr.toString()); + assertFalse(arr === res); + assertSame(Object.getPrototypeOf(arr), Object.getPrototypeOf(res)); + assertEquals("0,2,3", res.toString()); + } +})(); + +(function withIndex() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + var res = arr.with(1); + assertEquals("1,0,3", res.toString()); + } +})(); + +(function withIndexValue() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + var res = arr.with(1, 4); + assertEquals("1,4,3", res.toString()); + } +})(); + +(function withNegativeIndex() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + var res = arr.with(-2, 4); + assertEquals("1,4,3", res.toString()); + } +})(); + +(function withIndexTooLarge() { + for (var t = 0; t < types.length; t++) { + var type = types[t]; + var arr = new type([1, 2, 3]); + assertThrows(() => arr.with(3), RangeError); + } +})(); + +(function withIgnoresSymbolSpecies() { + var ta = new Int8Array([1, 2, 3]); + ta.constructor = { + [Symbol.species]: Uint8Array, + }; + + var res = ta.with(0, 4); + assertEquals(Object.getPrototypeOf(res), Int8Array.prototype); +})(); + +"success"; diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index 729423feba..63058c34d4 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -26,7 +26,7 @@ harness 22/115 (19.13%) isConstructor.js {unsupported: [Reflect.construct]} nativeFunctionMatcher.js -built-ins/Array 438/3055 (14.34%) +built-ins/Array 362/3055 (11.85%) fromAsync 94/94 (100.0%) from/calling-from-valid-1-noStrict.js non-strict Spec pretty clearly says this should be undefined from/elements-deleted-after.js Checking to see if length changed, but spec says it should not @@ -277,62 +277,9 @@ built-ins/Array 438/3055 (14.34%) prototype/toLocaleString/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toLocaleString/primitive_this_value.js strict prototype/toLocaleString/primitive_this_value_getter.js strict - prototype/toReversed/metadata 3/3 (100.0%) - prototype/toReversed/frozen-this-value.js - prototype/toReversed/get-descending-order.js - prototype/toReversed/holes-not-preserved.js - prototype/toReversed/ignores-species.js - prototype/toReversed/immutable.js - prototype/toReversed/length-casted-to-zero.js - prototype/toReversed/length-decreased-while-iterating.js - prototype/toReversed/length-exceeding-array-length-limit.js - prototype/toReversed/length-increased-while-iterating.js - prototype/toReversed/length-tolength.js prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/toReversed/this-value-boolean.js - prototype/toReversed/zero-or-one-element.js - prototype/toSorted/metadata 3/3 (100.0%) - prototype/toSorted/comparefn-called-after-get-elements.js - prototype/toSorted/comparefn-stop-after-error.js - prototype/toSorted/frozen-this-value.js - prototype/toSorted/holes-not-preserved.js - prototype/toSorted/ignores-species.js - prototype/toSorted/immutable.js - prototype/toSorted/length-casted-to-zero.js - prototype/toSorted/length-decreased-while-iterating.js - prototype/toSorted/length-exceeding-array-length-limit.js - prototype/toSorted/length-increased-while-iterating.js - prototype/toSorted/length-tolength.js prototype/toSorted/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/toSorted/this-value-boolean.js - prototype/toSorted/zero-or-one-element.js - prototype/toSpliced/metadata 3/3 (100.0%) - prototype/toSpliced/deleteCount-clamped-between-zero-and-remaining-count.js - prototype/toSpliced/deleteCount-missing.js - prototype/toSpliced/deleteCount-undefined.js - prototype/toSpliced/discarded-element-not-read.js - prototype/toSpliced/elements-read-in-order.js - prototype/toSpliced/frozen-this-value.js - prototype/toSpliced/holes-not-preserved.js - prototype/toSpliced/ignores-species.js - prototype/toSpliced/immutable.js - prototype/toSpliced/length-casted-to-zero.js - prototype/toSpliced/length-clamped-to-2pow53minus1.js - prototype/toSpliced/length-decreased-while-iterating.js - prototype/toSpliced/length-exceeding-array-length-limit.js - prototype/toSpliced/length-increased-while-iterating.js - prototype/toSpliced/length-tolength.js - prototype/toSpliced/mutate-while-iterating.js prototype/toSpliced/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/toSpliced/start-and-deleteCount-missing.js - prototype/toSpliced/start-and-deleteCount-undefineds.js - prototype/toSpliced/start-bigger-than-length.js - prototype/toSpliced/start-neg-infinity-is-zero.js - prototype/toSpliced/start-neg-less-than-minus-length-is-zero.js - prototype/toSpliced/start-neg-subtracted-from-length.js - prototype/toSpliced/start-undefined-and-deleteCount-missing.js - prototype/toSpliced/this-value-boolean.js - prototype/toSpliced/unmodified.js prototype/toString/call-with-boolean.js prototype/toString/non-callable-join-string-tag.js {unsupported: [Proxy, Reflect]} prototype/toString/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -343,22 +290,7 @@ built-ins/Array 438/3055 (14.34%) prototype/unshift/set-length-zero-array-length-is-non-writable.js prototype/unshift/throws-with-string-receiver.js prototype/values/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/with/metadata 3/3 (100.0%) - prototype/with/frozen-this-value.js - prototype/with/holes-not-preserved.js - prototype/with/ignores-species.js - prototype/with/immutable.js - prototype/with/index-bigger-or-eq-than-length.js - prototype/with/index-casted-to-number.js - prototype/with/index-negative.js - prototype/with/index-smaller-than-minus-length.js - prototype/with/length-decreased-while-iterating.js - prototype/with/length-exceeding-array-length-limit.js - prototype/with/length-increased-while-iterating.js - prototype/with/length-tolength.js - prototype/with/no-get-replaced-index.js prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/with/this-value-boolean.js prototype/methods-called-as-functions.js is-a-constructor.js {unsupported: [Reflect.construct]} proto-from-ctor-realm-one.js {unsupported: [Reflect]} @@ -2441,7 +2373,7 @@ built-ins/ThrowTypeError 8/14 (57.14%) unique-per-realm-non-simple.js unique-per-realm-unmapped-args.js -built-ins/TypedArray 1064/1386 (76.77%) +built-ins/TypedArray 1053/1386 (75.97%) from/arylk-get-length-error.js from/arylk-to-length-error.js from/from-array-mapper-detaches-result.js @@ -2989,10 +2921,10 @@ built-ins/TypedArray 1064/1386 (76.77%) prototype/toLocaleString/this-is-not-object.js prototype/toLocaleString/this-is-not-typedarray-instance.js prototype/toReversed/metadata 3/3 (100.0%) - prototype/toReversed 5/5 (100.0%) + prototype/toReversed/length-property-ignored.js + prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/toReversed/this-value-invalid.js prototype/toSorted/metadata 3/3 (100.0%) - prototype/toSorted/ignores-species.js - prototype/toSorted/immutable.js prototype/toSorted/length-property-ignored.js prototype/toSorted/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toSorted/this-value-invalid.js @@ -3013,13 +2945,6 @@ built-ins/TypedArray 1064/1386 (76.77%) prototype/values/this-is-not-typedarray-instance.js prototype/with/BigInt/early-type-coercion-bigint.js prototype/with/metadata 3/3 (100.0%) - prototype/with/early-type-coercion.js - prototype/with/ignores-species.js - prototype/with/immutable.js - prototype/with/index-bigger-or-eq-than-length.js - prototype/with/index-casted-to-number.js - prototype/with/index-negative.js - prototype/with/index-smaller-than-minus-length.js prototype/with/index-validated-against-current-length.js prototype/with/length-property-ignored.js prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -4967,7 +4892,7 @@ language/expressions/function 214/264 (81.06%) unscopables-with.js non-strict unscopables-with-in-nested-fn.js non-strict -language/expressions/generators 239/290 (82.41%) +language/expressions/generators 232/290 (80.0%) dstr/ary-init-iter-close.js dstr/ary-init-iter-get-err.js dstr/ary-init-iter-get-err-array-prototype.js @@ -7874,7 +7799,7 @@ language/statements/function 230/451 (51.0%) unscopables-with.js non-strict unscopables-with-in-nested-fn.js non-strict -language/statements/generators 224/266 (84.21%) +language/statements/generators 217/266 (81.58%) dstr/ary-init-iter-close.js dstr/ary-init-iter-get-err.js dstr/ary-init-iter-get-err-array-prototype.js