Commit 1ac9280d authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

Do not consult Symbol.species when constructing TypedArray from TypedArrays

Bug: v8:12744
Change-Id: I3e356c16554e8bc19afc06b18f4afd7fed2f228e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3563540
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Auto-Submit: Shu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79833}
parent 9238afb0
...@@ -77,8 +77,8 @@ transitioning macro AllocateTypedArray(implicit context: Context)( ...@@ -77,8 +77,8 @@ transitioning macro AllocateTypedArray(implicit context: Context)(
transitioning macro TypedArrayInitialize(implicit context: Context)( transitioning macro TypedArrayInitialize(implicit context: Context)(
initialize: constexpr bool, map: Map, length: uintptr, initialize: constexpr bool, map: Map, length: uintptr,
elementsInfo: typed_array::TypedArrayElementsInfo, elementsInfo: typed_array::TypedArrayElementsInfo):
bufferConstructor: JSReceiver): JSTypedArray labels IfRangeError { JSTypedArray labels IfRangeError {
const byteLength = elementsInfo.CalculateByteLength(length) const byteLength = elementsInfo.CalculateByteLength(length)
otherwise IfRangeError; otherwise IfRangeError;
const byteLengthNum = Convert<Number>(byteLength); const byteLengthNum = Convert<Number>(byteLength);
...@@ -86,11 +86,6 @@ transitioning macro TypedArrayInitialize(implicit context: Context)( ...@@ -86,11 +86,6 @@ transitioning macro TypedArrayInitialize(implicit context: Context)(
const byteOffset: uintptr = 0; const byteOffset: uintptr = 0;
try { try {
if (bufferConstructor != defaultConstructor) {
goto AttachOffHeapBuffer(ConstructWithTarget(
defaultConstructor, bufferConstructor, byteLengthNum));
}
if (byteLength > kMaxTypedArrayInHeap) goto AllocateOffHeap; if (byteLength > kMaxTypedArrayInHeap) goto AllocateOffHeap;
const buffer = AllocateEmptyOnHeapBuffer(); const buffer = AllocateEmptyOnHeapBuffer();
...@@ -131,10 +126,8 @@ transitioning macro ConstructByLength(implicit context: Context)( ...@@ -131,10 +126,8 @@ transitioning macro ConstructByLength(implicit context: Context)(
elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray { elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray {
try { try {
const length: uintptr = ToIndex(lengthObj) otherwise RangeError; const length: uintptr = ToIndex(lengthObj) otherwise RangeError;
const defaultConstructor: Constructor = GetArrayBufferFunction();
const initialize: constexpr bool = true; const initialize: constexpr bool = true;
return TypedArrayInitialize( return TypedArrayInitialize(initialize, map, length, elementsInfo)
initialize, map, length, elementsInfo, defaultConstructor)
otherwise RangeError; otherwise RangeError;
} label RangeError deferred { } label RangeError deferred {
ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, lengthObj); ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, lengthObj);
...@@ -145,12 +138,11 @@ transitioning macro ConstructByLength(implicit context: Context)( ...@@ -145,12 +138,11 @@ transitioning macro ConstructByLength(implicit context: Context)(
// ES #sec-typedarray-object // ES #sec-typedarray-object
transitioning macro ConstructByArrayLike(implicit context: Context)( transitioning macro ConstructByArrayLike(implicit context: Context)(
map: Map, arrayLike: HeapObject, length: uintptr, map: Map, arrayLike: HeapObject, length: uintptr,
elementsInfo: typed_array::TypedArrayElementsInfo, elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray {
bufferConstructor: JSReceiver): JSTypedArray {
try { try {
const initialize: constexpr bool = false; const initialize: constexpr bool = false;
const typedArray = TypedArrayInitialize( const typedArray =
initialize, map, length, elementsInfo, bufferConstructor) TypedArrayInitialize(initialize, map, length, elementsInfo)
otherwise RangeError; otherwise RangeError;
try { try {
...@@ -198,21 +190,18 @@ transitioning macro ConstructByArrayLike(implicit context: Context)( ...@@ -198,21 +190,18 @@ transitioning macro ConstructByArrayLike(implicit context: Context)(
// ES #sec-typedarray-object // ES #sec-typedarray-object
transitioning macro ConstructByIterable(implicit context: Context)( transitioning macro ConstructByIterable(implicit context: Context)(
iterable: JSReceiver, iteratorFn: Callable): never iterable: JSReceiver, iteratorFn: Callable): never
labels IfConstructByArrayLike(JSArray, uintptr, JSReceiver) { labels IfConstructByArrayLike(JSArray, uintptr) {
const array: JSArray = const array: JSArray =
IterableToListMayPreserveHoles(context, iterable, iteratorFn); IterableToListMayPreserveHoles(context, iterable, iteratorFn);
// Max JSArray length is a valid JSTypedArray length so we just use it. // Max JSArray length is a valid JSTypedArray length so we just use it.
goto IfConstructByArrayLike( goto IfConstructByArrayLike(array, array.length_uintptr);
array, array.length_uintptr, GetArrayBufferFunction());
} }
// 22.2.4.3 TypedArray ( typedArray ) // 22.2.4.3 TypedArray ( typedArray )
// ES #sec-typedarray-typedarray // ES #sec-typedarray-typedarray
transitioning macro ConstructByTypedArray(implicit context: Context)( transitioning macro ConstructByTypedArray(implicit context: Context)(
srcTypedArray: JSTypedArray): never srcTypedArray: JSTypedArray): never
labels IfConstructByArrayLike(JSTypedArray, uintptr, JSReceiver) { labels IfConstructByArrayLike(JSTypedArray, uintptr) {
let bufferConstructor: JSReceiver = GetArrayBufferFunction();
const srcBuffer: JSArrayBuffer = srcTypedArray.buffer;
let length: uintptr; let length: uintptr;
try { try {
// TODO(petermarshall): Throw on detached typedArray. // TODO(petermarshall): Throw on detached typedArray.
...@@ -222,20 +211,7 @@ transitioning macro ConstructByTypedArray(implicit context: Context)( ...@@ -222,20 +211,7 @@ transitioning macro ConstructByTypedArray(implicit context: Context)(
length = 0; length = 0;
} }
// The spec requires that constructing a typed array using a SAB-backed goto IfConstructByArrayLike(srcTypedArray, length);
// typed array use the ArrayBuffer constructor, not the species constructor.
// See https://tc39.github.io/ecma262/#sec-typedarray-typedarray.
if (!IsSharedArrayBuffer(srcBuffer)) {
bufferConstructor = SpeciesConstructor(srcBuffer, bufferConstructor);
try {
// TODO(petermarshall): Throw on detached typedArray.
length = LoadJSTypedArrayLengthAndCheckDetached(srcTypedArray)
otherwise DetachedOrOutOfBounds;
} label DetachedOrOutOfBounds {
length = 0;
}
}
goto IfConstructByArrayLike(srcTypedArray, length, bufferConstructor);
} }
// 22.2.4.5 TypedArray ( buffer, byteOffset, length ) // 22.2.4.5 TypedArray ( buffer, byteOffset, length )
...@@ -369,7 +345,7 @@ transitioning macro TypedArrayCreateByLength(implicit context: Context)( ...@@ -369,7 +345,7 @@ transitioning macro TypedArrayCreateByLength(implicit context: Context)(
transitioning macro ConstructByJSReceiver(implicit context: Context)( transitioning macro ConstructByJSReceiver(implicit context: Context)(
obj: JSReceiver): never obj: JSReceiver): never
labels IfConstructByArrayLike(JSReceiver, uintptr, JSReceiver) { labels IfConstructByArrayLike(JSReceiver, uintptr) {
try { try {
// TODO(v8:8906): Use iterator::GetIteratorMethod() once it supports // TODO(v8:8906): Use iterator::GetIteratorMethod() once it supports
// labels. // labels.
...@@ -385,7 +361,7 @@ transitioning macro ConstructByJSReceiver(implicit context: Context)( ...@@ -385,7 +361,7 @@ transitioning macro ConstructByJSReceiver(implicit context: Context)(
// anyway. // anyway.
const length: uintptr = ChangeSafeIntegerNumberToUintPtr(lengthNumber) const length: uintptr = ChangeSafeIntegerNumberToUintPtr(lengthNumber)
otherwise goto IfInvalidLength(lengthNumber); otherwise goto IfInvalidLength(lengthNumber);
goto IfConstructByArrayLike(obj, length, GetArrayBufferFunction()); goto IfConstructByArrayLike(obj, length);
} label IfInvalidLength(length: Number) { } label IfInvalidLength(length: Number) {
ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, length); ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, length);
} label IfIteratorNotCallable(_value: JSAny) deferred { } label IfIteratorNotCallable(_value: JSAny) deferred {
...@@ -428,14 +404,12 @@ transitioning builtin CreateTypedArray( ...@@ -428,14 +404,12 @@ transitioning builtin CreateTypedArray(
const elementsInfo = GetTypedArrayElementsInfo(map); const elementsInfo = GetTypedArrayElementsInfo(map);
return ConstructByLength(map, length, elementsInfo); return ConstructByLength(map, length, elementsInfo);
} label IfConstructByArrayLike( } label IfConstructByArrayLike(arrayLike: JSReceiver, length: uintptr) {
arrayLike: JSReceiver, length: uintptr, bufferConstructor: JSReceiver) {
const map = GetDerivedMap(target, newTarget); const map = GetDerivedMap(target, newTarget);
// 5. Let elementSize be the Number value of the Element Size value in Table // 5. Let elementSize be the Number value of the Element Size value in Table
// 56 for constructorName. // 56 for constructorName.
const elementsInfo = GetTypedArrayElementsInfo(map); const elementsInfo = GetTypedArrayElementsInfo(map);
return ConstructByArrayLike( return ConstructByArrayLike(map, arrayLike, length, elementsInfo);
map, arrayLike, length, elementsInfo, bufferConstructor);
} }
} }
......
...@@ -175,42 +175,6 @@ tests.push(function TestConstructFromTypedArray(constr) { ...@@ -175,42 +175,6 @@ tests.push(function TestConstructFromTypedArray(constr) {
} }
}); });
tests.push(function TestFromTypedArraySpecies(constr) {
var b = new ArrayBuffer(16);
var a1 = new constr(b);
var constructor_read = 0;
var cons = b.constructor;
Object.defineProperty(b, 'constructor', {
get: function() {
constructor_read++;
return cons;
}
});
var a2 = new constr(a1);
assertEquals(1, constructor_read);
});
tests.push(function TestFromTypedArraySpeciesDetachsBuffer(constr) {
var b = new ArrayBuffer(16);
var a1 = new constr(b);
var constructor_read = 0;
var cons = b.constructor;
Object.defineProperty(b, 'constructor', {
get: function() {
%ArrayBufferDetach(b);
return cons;
}
});
assertThrows(() => new constr(a1));
});
tests.push(function TestTypedArrayMaxLength(constr) { tests.push(function TestTypedArrayMaxLength(constr) {
var myObject = { 0: 5, 1: 6, length: %TypedArrayMaxLength() + 1 }; var myObject = { 0: 5, 1: 6, length: %TypedArrayMaxLength() + 1 };
......
// Copyright 2018 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: --allow-natives-syntax
var buffer = new ArrayBuffer(1024 * 1024);
buffer.constructor = {
[Symbol.species]: new Proxy(function() {}, {
get: _ => {
%ArrayBufferDetach(buffer);
}
})
};
var array1 = new Uint8Array(buffer, 0, 1024);
assertThrows(() => new Uint8Array(array1));
assertThrows(() => new Int8Array(array1));
...@@ -38,57 +38,6 @@ d8.file.execute('test/mjsunit/typedarray-helpers.js'); ...@@ -38,57 +38,6 @@ d8.file.execute('test/mjsunit/typedarray-helpers.js');
} }
})(); })();
(function ConstructFromTypedArraySpeciesConstructorDetaches() {
let rab;
class MyArrayBuffer extends ArrayBuffer {
constructor(...params) {
super(...params);
}
static get [Symbol.species]() {
%ArrayBufferDetach(rab);
}
};
function CreateRabForTest(ctor) {
const rab = new MyArrayBuffer(
4 * ctor.BYTES_PER_ELEMENT,
{maxByteLength: 8 * ctor.BYTES_PER_ELEMENT});
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
return rab;
}
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLength = new sourceCtor(rab, 0, 4);
assertThrows(() => { new targetCtor(fixedLength); }, TypeError);
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLengthWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
assertThrows(() => { new targetCtor(fixedLengthWithOffset); }, TypeError);
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTracking = new sourceCtor(rab, 0);
assertThrows(() => { new targetCtor(lengthTracking); }, TypeError);
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTrackingWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT);
assertThrows(() => { new targetCtor(lengthTrackingWithOffset); },
TypeError);
});
})();
(function AccessDetachedTypedArray() { (function AccessDetachedTypedArray() {
const rab = CreateResizableArrayBuffer(16, 40); const rab = CreateResizableArrayBuffer(16, 40);
......
...@@ -174,128 +174,6 @@ d8.file.execute('test/mjsunit/typedarray-helpers.js'); ...@@ -174,128 +174,6 @@ d8.file.execute('test/mjsunit/typedarray-helpers.js');
}); });
})(); })();
(function ConstructFromTypedArraySpeciesConstructorShrinks() {
let rab;
let resizeTo;
class MyArrayBuffer extends ArrayBuffer {
constructor(...params) {
super(...params);
}
static get [Symbol.species]() {
rab.resize(resizeTo);
}
};
function CreateRabForTest(ctor) {
const rab = new MyArrayBuffer(
4 * ctor.BYTES_PER_ELEMENT,
{maxByteLength: 8 * ctor.BYTES_PER_ELEMENT});
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
return rab;
}
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLength = new sourceCtor(rab, 0, 4);
resizeTo = 2 * sourceCtor.BYTES_PER_ELEMENT;
assertThrows(() => { new targetCtor(fixedLength); }, TypeError);
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLengthWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
resizeTo = 2 * sourceCtor.BYTES_PER_ELEMENT;
assertThrows(() => { new targetCtor(fixedLengthWithOffset); }, TypeError);
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTracking = new sourceCtor(rab, 0);
resizeTo = 2 * sourceCtor.BYTES_PER_ELEMENT;
assertEquals([0, 2], ToNumbers(new targetCtor(lengthTracking)));
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTrackingWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT);
resizeTo = 3 * sourceCtor.BYTES_PER_ELEMENT;
assertEquals([4], ToNumbers(new targetCtor(lengthTrackingWithOffset)));
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTrackingWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT);
resizeTo = 1 * sourceCtor.BYTES_PER_ELEMENT;
assertThrows(() => { new targetCtor(lengthTrackingWithOffset); },
TypeError);
});
})();
(function ConstructFromTypedArraySpeciesConstructorGrows() {
let rab;
let resizeTo;
class MyArrayBuffer extends ArrayBuffer {
constructor(...params) {
super(...params);
}
static get [Symbol.species]() {
rab.resize(resizeTo);
}
};
function CreateRabForTest(ctor) {
const rab = new MyArrayBuffer(
4 * ctor.BYTES_PER_ELEMENT,
{maxByteLength: 8 * ctor.BYTES_PER_ELEMENT});
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
return rab;
}
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLength = new sourceCtor(rab, 0, 4);
resizeTo = 6 * sourceCtor.BYTES_PER_ELEMENT;
// Fixed-length TA unaffected by growing.
assertEquals([0, 2, 4, 6], ToNumbers(new targetCtor(fixedLength)));
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const fixedLengthWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
resizeTo = 6 * sourceCtor.BYTES_PER_ELEMENT;
// Fixed-length TA unaffected by growing.
assertEquals([4, 6], ToNumbers(new targetCtor(fixedLengthWithOffset)));
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTracking = new sourceCtor(rab, 0);
resizeTo = 6 * sourceCtor.BYTES_PER_ELEMENT;
assertEquals([0, 2, 4, 6, 0, 0],
ToNumbers(new targetCtor(lengthTracking)));
});
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
rab = CreateRabForTest(sourceCtor);
const lengthTrackingWithOffset = new sourceCtor(
rab, 2 * sourceCtor.BYTES_PER_ELEMENT);
resizeTo = 6 * sourceCtor.BYTES_PER_ELEMENT;
assertEquals([4, 6, 0, 0],
ToNumbers(new targetCtor(lengthTrackingWithOffset)));
});
})();
(function TypedArrayLengthWhenResizedOutOfBounds1() { (function TypedArrayLengthWhenResizedOutOfBounds1() {
const rab = CreateResizableArrayBuffer(16, 40); const rab = CreateResizableArrayBuffer(16, 40);
......
...@@ -2880,9 +2880,6 @@ ...@@ -2880,9 +2880,6 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=12681 # https://bugs.chromium.org/p/v8/issues/detail?id=12681
'built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable': [FAIL], 'built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=12744
'built-ins/TypedArrayConstructors/ctors/no-species': [FAIL],
######################## NEEDS INVESTIGATION ########################### ######################## NEEDS INVESTIGATION ###########################
# https://bugs.chromium.org/p/v8/issues/detail?id=7833 # https://bugs.chromium.org/p/v8/issues/detail?id=7833
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment