[change-array-by-copy] Add TypedArray.prototype.toSorted
Bug: v8:12764 Change-Id: I1b48d4b685d0ce626da99ef5740edc1e1216ddc5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3907682 Reviewed-by: Marja Hölttä <marja@chromium.org> Auto-Submit: Shu-yu Guo <syg@chromium.org> Commit-Queue: Marja Hölttä <marja@chromium.org> Cr-Commit-Position: refs/heads/main@{#83370}
This commit is contained in:
parent
15f46fbc4c
commit
85925fc1e0
@ -891,6 +891,7 @@ filegroup(
|
||||
"src/builtins/typed-array-sort.tq",
|
||||
"src/builtins/typed-array-subarray.tq",
|
||||
"src/builtins/typed-array-to-reversed.tq",
|
||||
"src/builtins/typed-array-to-sorted.tq",
|
||||
"src/builtins/typed-array-values.tq",
|
||||
"src/builtins/typed-array-with.tq",
|
||||
"src/builtins/typed-array.tq",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -1790,6 +1790,7 @@ torque_files = [
|
||||
"src/builtins/typed-array-sort.tq",
|
||||
"src/builtins/typed-array-subarray.tq",
|
||||
"src/builtins/typed-array-to-reversed.tq",
|
||||
"src/builtins/typed-array-to-sorted.tq",
|
||||
"src/builtins/typed-array-values.tq",
|
||||
"src/builtins/typed-array-with.tq",
|
||||
"src/builtins/typed-array.tq",
|
||||
|
@ -79,32 +79,16 @@ TypedArrayMergeSort(implicit context: Context)(
|
||||
return Undefined;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.sort
|
||||
transitioning javascript builtin TypedArrayPrototypeSort(
|
||||
js-implicit context: NativeContext,
|
||||
receiver: JSAny)(...arguments): JSTypedArray {
|
||||
// 1. If comparefn is not undefined and IsCallable(comparefn) is false,
|
||||
// throw a TypeError exception.
|
||||
const comparefnObj: JSAny = arguments[0];
|
||||
if (comparefnObj != Undefined && !Is<Callable>(comparefnObj)) {
|
||||
ThrowTypeError(MessageTemplate::kBadSortComparisonFunction, comparefnObj);
|
||||
}
|
||||
|
||||
// 2. Let obj be the this value.
|
||||
const obj: JSAny = receiver;
|
||||
|
||||
// 3. Let buffer be ? ValidateTypedArray(obj).
|
||||
// 4. Let len be IntegerIndexedObjectLength(obj).
|
||||
let len: uintptr =
|
||||
ValidateTypedArrayAndGetLength(context, obj, kBuiltinNameSort);
|
||||
const array: JSTypedArray = UnsafeCast<JSTypedArray>(obj);
|
||||
|
||||
// Shared between TypedArray.prototype.sort and TypedArray.prototype.toSorted.
|
||||
transitioning macro TypedArraySortCommon(implicit context: Context)(
|
||||
array: JSTypedArray, len: uintptr, comparefnArg: Undefined|Callable,
|
||||
isSort: constexpr bool): JSTypedArray {
|
||||
// Arrays of length 1 or less are considered sorted.
|
||||
if (len < 2) return array;
|
||||
|
||||
// Default sorting is done in C++ using std::sort
|
||||
if (comparefnObj == Undefined) {
|
||||
return TypedArraySortFast(context, obj);
|
||||
if (comparefnArg == Undefined) {
|
||||
return TypedArraySortFast(context, array);
|
||||
}
|
||||
|
||||
// Throw rather than crash if the TypedArray's size exceeds max FixedArray
|
||||
@ -116,7 +100,7 @@ transitioning javascript builtin TypedArrayPrototypeSort(
|
||||
}
|
||||
|
||||
const comparefn: Callable =
|
||||
Cast<Callable>(comparefnObj) otherwise unreachable;
|
||||
Cast<Callable>(comparefnArg) otherwise unreachable;
|
||||
const accessor: TypedArrayAccessor =
|
||||
GetTypedArrayAccessor(array.elements_kind);
|
||||
|
||||
@ -134,25 +118,58 @@ transitioning javascript builtin TypedArrayPrototypeSort(
|
||||
|
||||
TypedArrayMergeSort(work2, 0, len, work1, array, comparefn);
|
||||
|
||||
// Reload the length; it's possible the backing ArrayBuffer has been resized
|
||||
// to be OOB or detached, in which case treat it as length 0.
|
||||
// If this is TypedArray.prototype.sort, reload the length; it's possible the
|
||||
// backing ArrayBuffer has been resized to be OOB or detached, in which case
|
||||
// treat it as length 0.
|
||||
//
|
||||
// This is not possible in TypedArray.prototype.toSorted as the array being
|
||||
// sorted is a copy that has not yet escaped to user script.
|
||||
|
||||
try {
|
||||
const newLen = LoadJSTypedArrayLengthAndCheckDetached(array)
|
||||
otherwise DetachedOrOutOfBounds;
|
||||
if (newLen < len) {
|
||||
len = newLen;
|
||||
let writebackLen = len;
|
||||
if constexpr (isSort) {
|
||||
try {
|
||||
const newLen = LoadJSTypedArrayLengthAndCheckDetached(array)
|
||||
otherwise DetachedOrOutOfBounds;
|
||||
if (newLen < writebackLen) {
|
||||
writebackLen = newLen;
|
||||
}
|
||||
} label DetachedOrOutOfBounds {
|
||||
writebackLen = 0;
|
||||
}
|
||||
} label DetachedOrOutOfBounds {
|
||||
len = 0;
|
||||
} else {
|
||||
dcheck(
|
||||
writebackLen ==
|
||||
LoadJSTypedArrayLengthAndCheckDetached(array) otherwise unreachable);
|
||||
}
|
||||
|
||||
// work1 contains the sorted numbers. Write them back.
|
||||
for (let i: uintptr = 0; i < len; ++i) {
|
||||
for (let i: uintptr = 0; i < writebackLen; ++i) {
|
||||
accessor.StoreNumeric(
|
||||
context, array, i, UnsafeCast<Numeric>(work1.objects[i]));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.sort
|
||||
transitioning javascript builtin TypedArrayPrototypeSort(
|
||||
js-implicit context: NativeContext,
|
||||
receiver: JSAny)(...arguments): JSTypedArray {
|
||||
// 1. If comparefn is not undefined and IsCallable(comparefn) is false,
|
||||
// throw a TypeError exception.
|
||||
const comparefnObj: JSAny = arguments[0];
|
||||
const comparefn = Cast<(Undefined | Callable)>(comparefnObj) otherwise
|
||||
ThrowTypeError(MessageTemplate::kBadSortComparisonFunction, comparefnObj);
|
||||
|
||||
// 2. Let obj be the this value.
|
||||
const obj: JSAny = receiver;
|
||||
|
||||
// 3. Let buffer be ? ValidateTypedArray(obj).
|
||||
// 4. Let len be IntegerIndexedObjectLength(obj).
|
||||
const len: uintptr =
|
||||
ValidateTypedArrayAndGetLength(context, obj, kBuiltinNameSort);
|
||||
const array: JSTypedArray = UnsafeCast<JSTypedArray>(obj);
|
||||
const kIsSort: constexpr bool = true;
|
||||
return TypedArraySortCommon(array, len, comparefn, kIsSort);
|
||||
}
|
||||
}
|
||||
|
59
src/builtins/typed-array-to-sorted.tq
Normal file
59
src/builtins/typed-array-to-sorted.tq
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
namespace typed_array {
|
||||
// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSorted
|
||||
|
||||
const kBuiltinNameToSorted: constexpr string =
|
||||
'%TypedArray%.prototype.toSorted';
|
||||
|
||||
transitioning javascript builtin TypedArrayPrototypeToSorted(
|
||||
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
|
||||
// 1. If comparefn is not undefined and IsCallable(comparefn) is false,
|
||||
// throw a TypeError exception.
|
||||
const comparefnObj: JSAny = arguments[0];
|
||||
const comparefn = Cast<(Undefined | Callable)>(comparefnObj) otherwise
|
||||
ThrowTypeError(MessageTemplate::kBadSortComparisonFunction, comparefnObj);
|
||||
|
||||
// 2. Let O be the this value.
|
||||
const obj: JSAny = receiver;
|
||||
|
||||
// 3. Perform ? ValidateTypedArray(O).
|
||||
// 4. Let buffer be obj.[[ViewedArrayBuffer]].
|
||||
// 5. Let len be O.[[ArrayLength]].
|
||||
const len: uintptr =
|
||||
ValidateTypedArrayAndGetLength(context, obj, kBuiltinNameToSorted);
|
||||
const array: JSTypedArray = UnsafeCast<JSTypedArray>(obj);
|
||||
|
||||
// 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »).
|
||||
const copy = TypedArrayCreateSameType(array, len);
|
||||
|
||||
// 7. NOTE: The following closure performs a numeric comparison rather than
|
||||
// the string comparison used in 1.1.1.5.
|
||||
// 8. Let SortCompare be a new Abstract Closure with parameters (x, y) that
|
||||
// captures comparefn and buffer and performs the following steps when
|
||||
// called:
|
||||
// a. Return ? CompareTypedArrayElements(x, y, comparefn, buffer).
|
||||
// 9. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
|
||||
// 10. Let j be 0.
|
||||
// 11. Repeat, while j < len,
|
||||
// a. Perform ! Set(A, ! ToString(𝔽(j)), sortedList[j], true).
|
||||
// b. Set j to j + 1.
|
||||
// 12. Return A.
|
||||
|
||||
// Perform the sorting by copying the source TypedArray and sorting the copy
|
||||
// in-place using the same code that as TypedArray.prototype.sort
|
||||
const info = GetTypedArrayElementsInfo(copy);
|
||||
const countBytes: uintptr =
|
||||
info.CalculateByteLength(len) otherwise unreachable;
|
||||
if (IsSharedArrayBuffer(array.buffer)) {
|
||||
CallCRelaxedMemmove(copy.data_ptr, array.data_ptr, countBytes);
|
||||
} else {
|
||||
CallCMemmove(copy.data_ptr, array.data_ptr, countBytes);
|
||||
}
|
||||
|
||||
const kIsSort: constexpr bool = false;
|
||||
return TypedArraySortCommon(copy, len, comparefn, kIsSort);
|
||||
}
|
||||
}
|
@ -4547,6 +4547,8 @@ void Genesis::InitializeGlobal_harmony_change_array_by_copy() {
|
||||
isolate());
|
||||
SimpleInstallFunction(isolate_, prototype, "toReversed",
|
||||
Builtin::kTypedArrayPrototypeToReversed, 0, true);
|
||||
SimpleInstallFunction(isolate_, prototype, "toSorted",
|
||||
Builtin::kTypedArrayPrototypeToSorted, 1, false);
|
||||
SimpleInstallFunction(isolate_, prototype, "with",
|
||||
Builtin::kTypedArrayPrototypeWith, 2, true);
|
||||
}
|
||||
|
@ -56,25 +56,25 @@ function TestToSortedBasicBehaviorHelper(input) {
|
||||
}
|
||||
|
||||
// Smi packed
|
||||
AssertToSortedAndSortSameResult([1,3,2,4]);
|
||||
TestToSortedBasicBehaviorHelper([1,3,2,4]);
|
||||
|
||||
// Double packed
|
||||
AssertToSortedAndSortSameResult([1.1,3.3,2.2,4.4]);
|
||||
TestToSortedBasicBehaviorHelper([1.1,3.3,2.2,4.4]);
|
||||
|
||||
// Packed
|
||||
AssertToSortedAndSortSameResult([true,false,1,42.42,null,"foo"]);
|
||||
TestToSortedBasicBehaviorHelper([true,false,1,42.42,null,"foo"]);
|
||||
|
||||
// Smi holey
|
||||
AssertToSortedAndSortSameResult([1,,3,,2,,4,,]);
|
||||
TestToSortedBasicBehaviorHelper([1,,3,,2,,4,,]);
|
||||
|
||||
// Double holey
|
||||
AssertToSortedAndSortSameResult([1.1,,3.3,,2.2,,4.4,,]);
|
||||
TestToSortedBasicBehaviorHelper([1.1,,3.3,,2.2,,4.4,,]);
|
||||
|
||||
// Holey
|
||||
AssertToSortedAndSortSameResult([true,,false,,1,,42.42,,null,,"foo",,]);
|
||||
TestToSortedBasicBehaviorHelper([true,,false,,1,,42.42,,null,,"foo",,]);
|
||||
|
||||
// Generic
|
||||
AssertToSortedAndSortSameResult({ length: 4,
|
||||
TestToSortedBasicBehaviorHelper({ length: 4,
|
||||
get "0"() { return "hello"; },
|
||||
get "1"() { return "cursed"; },
|
||||
get "2"() { return "java"; },
|
||||
|
299
test/mjsunit/harmony/typed-array-to-sorted.js
Normal file
299
test/mjsunit/harmony/typed-array-to-sorted.js
Normal file
@ -0,0 +1,299 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-change-array-by-copy --harmony-rab-gsab
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
d8.file.execute('test/mjsunit/typedarray-helpers.js');
|
||||
|
||||
const TAProto = Object.getPrototypeOf(Int8Array.prototype);
|
||||
|
||||
function AssertToSortedAndSortSameResult(input, ...args) {
|
||||
const orig = input.slice();
|
||||
const s = TAProto.toSorted.apply(input, args);
|
||||
const copy = input.slice();
|
||||
TAProto.sort.apply(copy, args);
|
||||
|
||||
// The in-place sorted version should be pairwise equal to the toSorted
|
||||
// version.
|
||||
assertEquals(copy, s);
|
||||
|
||||
// The original input should be unchanged.
|
||||
assertEquals(orig, input);
|
||||
|
||||
// The result of toSorted() is a copy.
|
||||
assertFalse(s === input);
|
||||
}
|
||||
|
||||
function TestToSortedBasicBehaviorHelper(input) {
|
||||
// No custom comparator.
|
||||
AssertToSortedAndSortSameResult(input);
|
||||
// Custom comparator.
|
||||
AssertToSortedAndSortSameResult(input, (x, y) => {
|
||||
if (x < y) return -1;
|
||||
if (x > y) return 1;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
(function TestSurface() {
|
||||
for (let TA of ctors) {
|
||||
assertEquals(1, TA.prototype.toSorted.length);
|
||||
assertEquals("toSorted", TA.prototype.toSorted.name);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestBasic() {
|
||||
for (let TA of ctors) {
|
||||
let a = new TA(4);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(a, i, (Math.random() * 100)|0);
|
||||
}
|
||||
TestToSortedBasicBehaviorHelper(a);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestResizableBuffer() {
|
||||
for (let TA of ctors) {
|
||||
const rab = CreateResizableArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const fixedLength = new TA(rab, 0, 4);
|
||||
const fixedLengthWithOffset = new TA(rab, 2 * TA.BYTES_PER_ELEMENT, 2);
|
||||
const lengthTracking = new TA(rab, 0);
|
||||
const lengthTrackingWithOffset = new TA(rab, 2 * TA.BYTES_PER_ELEMENT);
|
||||
|
||||
// Write some data into the array.
|
||||
const taWrite = new TA(rab);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(taWrite, i, (Math.random() * 100)|0);
|
||||
}
|
||||
|
||||
// a, b, c, d, below represent random values.
|
||||
//
|
||||
// Orig. array: [a, b, c, d]
|
||||
// [a, b, c, d] << fixedLength
|
||||
// [c, d] << fixedLengthWithOffset
|
||||
// [a, b, c, d, ...] << lengthTracking
|
||||
// [c, d, ...] << lengthTrackingWithOffset
|
||||
|
||||
TestToSortedBasicBehaviorHelper(fixedLength);
|
||||
TestToSortedBasicBehaviorHelper(fixedLengthWithOffset);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
TestToSortedBasicBehaviorHelper(lengthTrackingWithOffset);
|
||||
|
||||
// Shrink so that the TAs with offset go out of bounds.
|
||||
rab.resize(1 * TA.BYTES_PER_ELEMENT);
|
||||
WriteToTypedArray(taWrite, 0, 0);
|
||||
|
||||
assertThrows(() => { fixedLength.toSorted(); }, TypeError);
|
||||
assertThrows(() => { fixedLengthWithOffset.toSorted(); }, TypeError);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
assertThrows(() => { lengthTrackingWithOffset.toSorted(); }, TypeError);
|
||||
|
||||
// Shrink to zero.
|
||||
rab.resize(0);
|
||||
|
||||
assertThrows(() => { fixedLength.toSorted(); }, TypeError);
|
||||
assertThrows(() => { fixedLengthWithOffset.toSorted(); }, TypeError);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
assertThrows(() => { lengthTrackingWithOffset.toSorted(); }, TypeError);
|
||||
|
||||
// Grow so that all TAs are back in-bounds.
|
||||
rab.resize(6 * TA.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
WriteToTypedArray(taWrite, i, (Math.random() * 100)|0);
|
||||
}
|
||||
|
||||
// Orig. array: [a, b, c, d, e, f]
|
||||
// [a, b, c, d] << fixedLength
|
||||
// [c, d] << fixedLengthWithOffset
|
||||
// [a, b, c, d, e, f, ...] << lengthTracking
|
||||
// [c, d, e, f, ...] << lengthTrackingWithOffset
|
||||
|
||||
TestToSortedBasicBehaviorHelper(fixedLength);
|
||||
TestToSortedBasicBehaviorHelper(fixedLengthWithOffset);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
TestToSortedBasicBehaviorHelper(lengthTrackingWithOffset);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestComparatorShrinks() {
|
||||
for (let TA of ctors) {
|
||||
const rab = CreateResizableArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const lengthTracking = new TA(rab, 0);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(lengthTracking, i, (Math.random() * 100)|0)
|
||||
}
|
||||
|
||||
let resized = false;
|
||||
const evilComparator = (x, y) => {
|
||||
if (!resized) {
|
||||
resized = true;
|
||||
rab.resize(2 * TA.BYTES_PER_ELEMENT);
|
||||
}
|
||||
if (x < y) return -1;
|
||||
if (x > y) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Shrinks don't affect toSorted because sorting is done on a snapshot taken
|
||||
// at the beginning.
|
||||
let s = lengthTracking.toSorted(evilComparator);
|
||||
assertEquals(4, s.length);
|
||||
// Source shrunk.
|
||||
assertEquals(2, lengthTracking.length);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestComparatorGrows() {
|
||||
for (let TA of ctors) {
|
||||
const rab = CreateResizableArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const lengthTracking = new TA(rab, 0);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(lengthTracking, i, (Math.random() * 100)|0)
|
||||
}
|
||||
|
||||
let resized = false;
|
||||
const evilComparator = (x, y) => {
|
||||
if (!resized) {
|
||||
resized = true;
|
||||
rab.resize(6 * TA.BYTES_PER_ELEMENT);
|
||||
}
|
||||
if (x < y) return -1;
|
||||
if (x > y) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Grows also don't affect toSorted because sorting is done on a snapshot
|
||||
// taken at the beginning.
|
||||
let s = lengthTracking.toSorted(evilComparator);
|
||||
assertEquals(4, s.length);
|
||||
// Source grew.
|
||||
assertEquals(6, lengthTracking.length);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestComparatorDetaches() {
|
||||
for (let TA of ctors) {
|
||||
const rab = CreateResizableArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const lengthTracking = new TA(rab, 0);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(lengthTracking, i, (Math.random() * 100)|0)
|
||||
}
|
||||
|
||||
let detached = false;
|
||||
const evilComparator = (x, y) => {
|
||||
if (!detached) {
|
||||
detached = true;
|
||||
%ArrayBufferDetach(rab);
|
||||
}
|
||||
if (x < y) return -1;
|
||||
if (x > y) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Detaching also don't affect toSorted because sorting is done on a snapshot
|
||||
// taken at the beginning.
|
||||
let s = lengthTracking.toSorted(evilComparator);
|
||||
assertEquals(4, s.length);
|
||||
// Source is detached.
|
||||
assertEquals(0, lengthTracking.length);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestGrowableSAB() {
|
||||
for (let TA of ctors) {
|
||||
const gsab = CreateGrowableSharedArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const fixedLength = new TA(gsab, 0, 4);
|
||||
const fixedLengthWithOffset = new TA(gsab, 2 * TA.BYTES_PER_ELEMENT, 2);
|
||||
const lengthTracking = new TA(gsab, 0);
|
||||
const lengthTrackingWithOffset = new TA(gsab, 2 * TA.BYTES_PER_ELEMENT);
|
||||
|
||||
// Write some data into the array.
|
||||
const taWrite = new TA(gsab);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(taWrite, i, (Math.random() * 100)|0);
|
||||
}
|
||||
|
||||
// Orig. array: [a, b, c, d]
|
||||
// [a, b, c, d] << fixedLength
|
||||
// [c, d] << fixedLengthWithOffset
|
||||
// [a, b, c, d, ...] << lengthTracking
|
||||
// [c, d, ...] << lengthTrackingWithOffset
|
||||
TestToSortedBasicBehaviorHelper(fixedLength);
|
||||
TestToSortedBasicBehaviorHelper(fixedLengthWithOffset);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
TestToSortedBasicBehaviorHelper(lengthTrackingWithOffset);
|
||||
|
||||
// Grow.
|
||||
gsab.grow(6 * TA.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
WriteToTypedArray(taWrite, i, (Math.random() * 100)|0);
|
||||
}
|
||||
|
||||
// Orig. array: [a, b, c, d, e, f]
|
||||
// [a, b, c, d] << fixedLength
|
||||
// [c, d] << fixedLengthWithOffset
|
||||
// [a, b, c, d, e, f, ...] << lengthTracking
|
||||
// [c, d, e, f, ...] << lengthTrackingWithOffset
|
||||
TestToSortedBasicBehaviorHelper(fixedLength);
|
||||
TestToSortedBasicBehaviorHelper(fixedLengthWithOffset);
|
||||
TestToSortedBasicBehaviorHelper(lengthTracking);
|
||||
TestToSortedBasicBehaviorHelper(lengthTrackingWithOffset);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestComparatorGrows() {
|
||||
for (let TA of ctors) {
|
||||
const gsab = CreateGrowableSharedArrayBuffer(4 * TA.BYTES_PER_ELEMENT,
|
||||
8 * TA.BYTES_PER_ELEMENT);
|
||||
const lengthTracking = new TA(gsab, 0);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
WriteToTypedArray(lengthTracking, i, (Math.random() * 100)|0)
|
||||
}
|
||||
|
||||
let resized = false;
|
||||
const evilComparator = (x, y) => {
|
||||
if (!resized) {
|
||||
resized = true;
|
||||
gsab.grow(6 * TA.BYTES_PER_ELEMENT);
|
||||
}
|
||||
if (x < y) return -1;
|
||||
if (x > y) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Grows also don't affect toSorted because sorting is done on a snapshot
|
||||
// taken at the beginning.
|
||||
let s = lengthTracking.toSorted(evilComparator);
|
||||
assertEquals(4, s.length);
|
||||
// Source grew.
|
||||
assertEquals(6, lengthTracking.length);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestNonTypedArray() {
|
||||
for (let TA of ctors) {
|
||||
assertThrows(() => { TA.prototype.toSorted.call([1,2,3,4]); }, TypeError);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestDetached() {
|
||||
for (let TA of ctors) {
|
||||
let a = new TA(4);
|
||||
%ArrayBufferDetach(a.buffer);
|
||||
assertThrows(() => { a.toSorted(); }, TypeError);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestNoSpecies() {
|
||||
class MyUint8Array extends Uint8Array {
|
||||
static get [Symbol.species]() { return MyUint8Array; }
|
||||
}
|
||||
assertEquals(Uint8Array, (new MyUint8Array()).toSorted().constructor);
|
||||
})();
|
@ -552,30 +552,30 @@ KNOWN_OBJECTS = {
|
||||
("old_space", 0x04549): "StringSplitCache",
|
||||
("old_space", 0x04951): "RegExpMultipleCache",
|
||||
("old_space", 0x04d59): "BuiltinsConstantsTable",
|
||||
("old_space", 0x051ad): "AsyncFunctionAwaitRejectSharedFun",
|
||||
("old_space", 0x051d1): "AsyncFunctionAwaitResolveSharedFun",
|
||||
("old_space", 0x051f5): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
("old_space", 0x05219): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
("old_space", 0x0523d): "AsyncGeneratorYieldResolveSharedFun",
|
||||
("old_space", 0x05261): "AsyncGeneratorReturnResolveSharedFun",
|
||||
("old_space", 0x05285): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
("old_space", 0x052a9): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
("old_space", 0x052cd): "AsyncIteratorValueUnwrapSharedFun",
|
||||
("old_space", 0x052f1): "PromiseAllResolveElementSharedFun",
|
||||
("old_space", 0x05315): "PromiseAllSettledResolveElementSharedFun",
|
||||
("old_space", 0x05339): "PromiseAllSettledRejectElementSharedFun",
|
||||
("old_space", 0x0535d): "PromiseAnyRejectElementSharedFun",
|
||||
("old_space", 0x05381): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
("old_space", 0x053a5): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
("old_space", 0x053c9): "PromiseCatchFinallySharedFun",
|
||||
("old_space", 0x053ed): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
("old_space", 0x05411): "PromiseThenFinallySharedFun",
|
||||
("old_space", 0x05435): "PromiseThrowerFinallySharedFun",
|
||||
("old_space", 0x05459): "PromiseValueThunkFinallySharedFun",
|
||||
("old_space", 0x0547d): "ProxyRevokeSharedFun",
|
||||
("old_space", 0x054a1): "ShadowRealmImportValueFulfilledSFI",
|
||||
("old_space", 0x054c5): "SourceTextModuleExecuteAsyncModuleFulfilledSFI",
|
||||
("old_space", 0x054e9): "SourceTextModuleExecuteAsyncModuleRejectedSFI",
|
||||
("old_space", 0x051b1): "AsyncFunctionAwaitRejectSharedFun",
|
||||
("old_space", 0x051d5): "AsyncFunctionAwaitResolveSharedFun",
|
||||
("old_space", 0x051f9): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
("old_space", 0x0521d): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
("old_space", 0x05241): "AsyncGeneratorYieldResolveSharedFun",
|
||||
("old_space", 0x05265): "AsyncGeneratorReturnResolveSharedFun",
|
||||
("old_space", 0x05289): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
("old_space", 0x052ad): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
("old_space", 0x052d1): "AsyncIteratorValueUnwrapSharedFun",
|
||||
("old_space", 0x052f5): "PromiseAllResolveElementSharedFun",
|
||||
("old_space", 0x05319): "PromiseAllSettledResolveElementSharedFun",
|
||||
("old_space", 0x0533d): "PromiseAllSettledRejectElementSharedFun",
|
||||
("old_space", 0x05361): "PromiseAnyRejectElementSharedFun",
|
||||
("old_space", 0x05385): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
("old_space", 0x053a9): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
("old_space", 0x053cd): "PromiseCatchFinallySharedFun",
|
||||
("old_space", 0x053f1): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
("old_space", 0x05415): "PromiseThenFinallySharedFun",
|
||||
("old_space", 0x05439): "PromiseThrowerFinallySharedFun",
|
||||
("old_space", 0x0545d): "PromiseValueThunkFinallySharedFun",
|
||||
("old_space", 0x05481): "ProxyRevokeSharedFun",
|
||||
("old_space", 0x054a5): "ShadowRealmImportValueFulfilledSFI",
|
||||
("old_space", 0x054c9): "SourceTextModuleExecuteAsyncModuleFulfilledSFI",
|
||||
("old_space", 0x054ed): "SourceTextModuleExecuteAsyncModuleRejectedSFI",
|
||||
}
|
||||
|
||||
# Lower 32 bits of first page addresses for various heap spaces.
|
||||
|
Loading…
Reference in New Issue
Block a user