[typedarrays] Check detached buffer at start of typed array methods

- Throw TypeError in ValidateTypedArray, matching JSC, SpiderMonkey
  and ChakraCore.
- Validate typed arrays at start of each typed array prototype
  methods in src/js/typedarrays.js
- Add tests to check detached buffers
- Remove an unnecessary parameter of TypedArraySpeciesCreate
  in src/js/typedarrays.js
- Standardize TypedArray.prototype.subarray
- Update test262.status to pass detached buffer tests

BUG=v8:4648,v8:4665,v8:4953

Review-Url: https://codereview.chromium.org/2778623003
Cr-Commit-Position: refs/heads/master@{#44357}
This commit is contained in:
cwhan.tunz 2017-04-03 20:48:48 -07:00 committed by Commit bot
parent 6cdd377586
commit 238d5b4453
25 changed files with 262 additions and 98 deletions

View File

@ -17,7 +17,8 @@ namespace internal {
// ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
BUILTIN(TypedArrayPrototypeBuffer) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
CHECK_RECEIVER(JSTypedArray, typed_array,
"get %TypedArray%.prototype.buffer");
return *typed_array->GetBuffer();
}
@ -128,8 +129,6 @@ BUILTIN(TypedArrayPrototypeCopyWithin) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
if (V8_UNLIKELY(array->WasNeutered())) return *array;
int64_t len = array->length_value();
int64_t to = 0;
int64_t from = 0;
@ -193,8 +192,6 @@ BUILTIN(TypedArrayPrototypeFill) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
if (V8_UNLIKELY(array->WasNeutered())) return *array;
int64_t len = array->length_value();
int64_t start = 0;
int64_t end = len;
@ -340,8 +337,6 @@ BUILTIN(TypedArrayPrototypeReverse) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
if (V8_UNLIKELY(array->WasNeutered())) return *array;
ElementsAccessor* elements = array->GetElementsAccessor();
elements->Reverse(*array);
return *array;

View File

@ -86,6 +86,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
case Runtime::kInlineArrayBufferViewGetByteOffset:
return ReduceArrayBufferViewField(
node, AccessBuilder::ForJSArrayBufferViewByteOffset());
case Runtime::kInlineArrayBufferViewWasNeutered:
return ReduceArrayBufferViewWasNeutered(node);
case Runtime::kInlineMaxSmi:
return ReduceMaxSmi(node);
case Runtime::kInlineTypedArrayGetLength:
@ -374,6 +376,22 @@ Reduction JSIntrinsicLowering::ReduceArrayBufferViewField(
return Replace(value);
}
Reduction JSIntrinsicLowering::ReduceArrayBufferViewWasNeutered(Node* node) {
Node* receiver = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Check if the {receiver}s buffer was neutered.
Node* receiver_buffer = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
receiver, effect, control);
Node* value = effect = graph()->NewNode(
simplified()->ArrayBufferWasNeutered(), receiver_buffer, effect, control);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Reduction JSIntrinsicLowering::ReduceMaxSmi(Node* node) {
Node* value = jsgraph()->Constant(Smi::kMaxValue);
ReplaceWithValue(node, value);

View File

@ -68,6 +68,7 @@ class V8_EXPORT_PRIVATE JSIntrinsicLowering final
// TODO(turbofan): typedarray.js support; drop once TypedArrays are
// converted to proper CodeStubAssembler based builtins.
Reduction ReduceArrayBufferViewField(Node* node, FieldAccess const& access);
Reduction ReduceArrayBufferViewWasNeutered(Node* node);
Reduction ReduceMaxSmi(Node* node);
Reduction ReduceTypedArrayMaxSizeInHeap(Node* node);

View File

@ -9924,6 +9924,23 @@ void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
}
void HOptimizedGraphBuilder::GenerateArrayBufferViewWasNeutered(
CallRuntime* expr) {
NoObservableSideEffectsScope scope(this);
DCHECK_EQ(expr->arguments()->length(), 1);
CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
HValue* view = Pop();
HInstruction* buffer = Add<HLoadNamedField>(
view, nullptr, HObjectAccess::ForJSArrayBufferViewBuffer());
HInstruction* flags = Add<HLoadNamedField>(
buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
HValue* was_neutered_mask =
Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
HValue* was_neutered =
AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
return ast_context()->ReturnValue(was_neutered);
}
void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
CallRuntime* expr) {

View File

@ -2175,6 +2175,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder,
F(TypedArrayMaxSizeInHeap) \
F(ArrayBufferViewGetByteLength) \
F(ArrayBufferViewGetByteOffset) \
F(ArrayBufferViewWasNeutered) \
F(TypedArrayGetLength) \
/* ArrayBuffer */ \
F(ArrayBufferGetByteLength) \

View File

@ -13,7 +13,6 @@
// array.js has to come before typedarray.js for this to work
var ArrayToString = utils.ImportNow("ArrayToString");
var ArrayValues;
var GetIterator;
var GetMethod;
var GlobalArray = global.Array;
@ -56,7 +55,6 @@ TYPED_ARRAYS(DECLARE_GLOBALS)
var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
utils.Import(function(from) {
ArrayValues = from.ArrayValues;
GetIterator = from.GetIterator;
GetMethod = from.GetMethod;
InnerArrayFilter = from.InnerArrayFilter;
@ -74,6 +72,14 @@ utils.Import(function(from) {
// --------------- Typed Arrays ---------------------
// ES6 section 22.2.3.5.1 ValidateTypedArray ( O )
function ValidateTypedArray(array, methodName) {
if (!IS_TYPEDARRAY(array)) throw %make_type_error(kNotTypedArray);
if (%_ArrayBufferViewWasNeutered(array))
throw %make_type_error(kDetachedOperation, methodName);
}
function TypedArrayDefaultConstructor(typedArray) {
switch (%_ClassOf(typedArray)) {
macro TYPED_ARRAY_CONSTRUCTOR_CASE(NAME, ELEMENT_SIZE)
@ -94,20 +100,16 @@ function TypedArrayCreate(constructor, arg0, arg1, arg2) {
} else {
var newTypedArray = new constructor(arg0, arg1, arg2);
}
if (!IS_TYPEDARRAY(newTypedArray)) throw %make_type_error(kNotTypedArray);
// TODO(littledan): Check for being detached, here and elsewhere
// All callers where the first argument is a Number have no additional
// arguments.
ValidateTypedArray(newTypedArray, "TypedArrayCreate");
if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
throw %make_type_error(kTypedArrayTooShort);
}
return newTypedArray;
}
function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) {
function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2) {
var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
var constructor = SpeciesConstructor(exemplar, defaultConstructor,
conservative);
var constructor = SpeciesConstructor(exemplar, defaultConstructor);
return TypedArrayCreate(constructor, arg0, arg1, arg2);
}
@ -207,10 +209,8 @@ function NAMESubArray(begin, end) {
var newLength = endInt - beginInt;
var beginByteOffset =
%_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
// BUG(v8:4665): For web compatibility, subarray needs to always build an
// instance of the default constructor.
// TODO(littledan): Switch to the standard or standardize the fix
return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength);
return TypedArraySpeciesCreate(this, %TypedArrayGetBuffer(this),
beginByteOffset, newLength);
}
endmacro
@ -225,7 +225,7 @@ endmacro
TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
}
throw %make_type_error(kIncompatibleMethodReceiver,
"get TypedArray.prototype.subarray", this);
"get %TypedArray%.prototype.subarray", this);
}
%SetForceInlineFlag(TypedArraySubArray);
@ -361,7 +361,7 @@ function InnerTypedArrayEvery(f, receiver, array, length) {
// ES6 draft 05-05-15, section 22.2.3.7
function TypedArrayEvery(f, receiver) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.every");
var length = %_TypedArrayGetLength(this);
@ -391,7 +391,7 @@ function InnerTypedArrayForEach(f, receiver, array, length) {
// ES6 draft 08-24-14, section 22.2.3.12
function TypedArrayForEach(f, receiver) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.forEach");
var length = %_TypedArrayGetLength(this);
@ -402,7 +402,7 @@ function TypedArrayForEach(f, receiver) {
// ES6 draft 07-15-13, section 22.2.3.9
function TypedArrayFilter(f, thisArg) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypeArray%.prototype.filter");
var length = %_TypedArrayGetLength(this);
if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f);
@ -420,7 +420,7 @@ function TypedArrayFilter(f, thisArg) {
// ES6 draft 07-15-13, section 22.2.3.10
function TypedArrayFind(predicate, thisArg) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.find");
var length = %_TypedArrayGetLength(this);
@ -431,7 +431,7 @@ function TypedArrayFind(predicate, thisArg) {
// ES6 draft 07-15-13, section 22.2.3.11
function TypedArrayFindIndex(predicate, thisArg) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.findIndex");
var length = %_TypedArrayGetLength(this);
@ -442,7 +442,7 @@ function TypedArrayFindIndex(predicate, thisArg) {
// ES6 draft 05-18-15, section 22.2.3.25
function TypedArraySort(comparefn) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.sort");
var length = %_TypedArrayGetLength(this);
@ -456,7 +456,7 @@ function TypedArraySort(comparefn) {
// ES6 draft 07-15-13, section 22.2.3.18
function TypedArrayMap(f, thisArg) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.map");
var length = %_TypedArrayGetLength(this);
var result = TypedArraySpeciesCreate(this, length);
@ -483,7 +483,7 @@ function InnerTypedArraySome(f, receiver, array, length) {
// ES6 draft 05-05-15, section 22.2.3.24
function TypedArraySome(f, receiver) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.some");
var length = %_TypedArrayGetLength(this);
@ -494,7 +494,7 @@ function TypedArraySome(f, receiver) {
// ES6 section 22.2.3.27
function TypedArrayToLocaleString() {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.toLocaleString");
var length = %_TypedArrayGetLength(this);
@ -504,7 +504,7 @@ function TypedArrayToLocaleString() {
// ES6 section 22.2.3.14
function TypedArrayJoin(separator) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.join");
var length = %_TypedArrayGetLength(this);
@ -539,7 +539,7 @@ function InnerTypedArrayReduce(
// ES6 draft 07-15-13, section 22.2.3.19
function TypedArrayReduce(callback, current) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.reduce");
var length = %_TypedArrayGetLength(this);
return InnerTypedArrayReduce(
@ -575,7 +575,7 @@ function InnerArrayReduceRight(callback, current, array, length,
// ES6 draft 07-15-13, section 22.2.3.19
function TypedArrayReduceRight(callback, current) {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
ValidateTypedArray(this, "%TypedArray%.prototype.reduceRight");
var length = %_TypedArrayGetLength(this);
return InnerArrayReduceRight(callback, current, this, length,

View File

@ -6914,8 +6914,18 @@ MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate,
THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray);
}
// TODO(caitp): throw if array.[[ViewedArrayBuffer]] is neutered (per v8:4648)
return Handle<JSTypedArray>::cast(receiver);
Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
if (V8_UNLIKELY(array->WasNeutered())) {
const MessageTemplate::Template message =
MessageTemplate::kDetachedOperation;
Handle<String> operation =
isolate->factory()->NewStringFromAsciiChecked(method_name);
THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray);
}
// spec describes to return `buffer`, but it may disrupt current
// implementations, and it's much useful to return array for now.
return array;
}
#ifdef VERIFY_HEAP

View File

@ -56,6 +56,12 @@ BUFFER_VIEW_GETTER(TypedArray, Length, length)
#undef BUFFER_VIEW_GETTER
RUNTIME_FUNCTION(Runtime_ArrayBufferViewWasNeutered) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(JSTypedArray::cast(args[0])->WasNeutered());
}
RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
@ -214,7 +220,6 @@ RUNTIME_FUNCTION(Runtime_IsTypedArray) {
return isolate->heap()->ToBoolean(args[0]->IsJSTypedArray());
}
RUNTIME_FUNCTION(Runtime_IsSharedTypedArray) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -613,19 +613,20 @@ namespace internal {
F(WasmNumInterpretedCalls, 1, 1) \
F(RedirectToWasmInterpreter, 2, 1)
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \
F(ArrayBufferViewGetByteLength, 1, 1) \
F(ArrayBufferViewGetByteOffset, 1, 1) \
F(TypedArrayGetLength, 1, 1) \
F(TypedArrayGetBuffer, 1, 1) \
F(TypedArraySetFastCases, 3, 1) \
F(TypedArraySortFast, 1, 1) \
F(TypedArrayMaxSizeInHeap, 0, 1) \
F(IsTypedArray, 1, 1) \
F(IsSharedTypedArray, 1, 1) \
F(IsSharedIntegerTypedArray, 1, 1) \
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \
F(ArrayBufferViewGetByteLength, 1, 1) \
F(ArrayBufferViewGetByteOffset, 1, 1) \
F(ArrayBufferViewWasNeutered, 1, 1) \
F(TypedArrayGetLength, 1, 1) \
F(TypedArrayGetBuffer, 1, 1) \
F(TypedArraySetFastCases, 3, 1) \
F(TypedArraySortFast, 1, 1) \
F(TypedArrayMaxSizeInHeap, 0, 1) \
F(IsTypedArray, 1, 1) \
F(IsSharedTypedArray, 1, 1) \
F(IsSharedIntegerTypedArray, 1, 1) \
F(IsSharedInteger32TypedArray, 1, 1)
#define FOR_EACH_INTRINSIC_WASM(F) \

View File

@ -240,8 +240,6 @@ CheckEachTypedArray(function parametersNotCalledIfDetached(constructor) {
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
// TODO(caitp): this should throw due to being invoked on a TypedArray with a
// detached buffer (per v8:4648).
array.copyWithin(tmp, tmp, tmp);
assertThrows(() => array.copyWithin(tmp, tmp, tmp), TypeError);
assertEquals(0, array.length, "array.[[ViewedArrayBuffer]] is detached");
});

View File

@ -159,6 +159,11 @@ function TestTypedArrayForEach(constructor) {
assertEquals(Array.prototype.every.call(a,
function(elt) { x += elt; return true; }), true);
assertEquals(x, 4);
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.every(() => true), TypeError);
}
for (i = 0; i < typedArrayConstructors.length; i++) {

View File

@ -2,6 +2,8 @@
// 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 intArrayConstructors = [
Uint8Array,
Int8Array,
@ -76,6 +78,19 @@ Symbol(Symbol.toStringTag)
assertArrayEquals([3, 3], [a[0], a[1]]);
Array.prototype.fill.call(a, 4);
assertArrayEquals([4, 3], [a[0], a[1]]);
// Detached Operation
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.fill(tmp), TypeError);
}
for (var constructor of intArrayConstructors) {

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -184,4 +186,17 @@ assertEquals(Array.prototype.find.call(a,
function(elt) { x += elt; return false; }), undefined);
assertEquals(x, 4);
// Detached Operation
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.find(tmp), TypeError);
}

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -184,4 +186,17 @@ assertEquals(Array.prototype.findIndex.call(a,
function(elt) { x += elt; return false; }), -1);
assertEquals(x, 4);
// Detached Operation
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.findIndex(tmp), TypeError);
}

View File

@ -148,6 +148,11 @@ function TestTypedArrayForEach(constructor) {
assertEquals(Array.prototype.forEach.call(a,
function(elt) { x += elt; }), undefined);
assertEquals(x, 4);
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.forEach(() => true), TypeError);
}
for (i = 0; i < typedArrayConstructors.length; i++) {

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -14,6 +16,14 @@ var typedArrayConstructors = [
Float64Array
];
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
for (var constructor of typedArrayConstructors) {
var array = new constructor([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]);
@ -53,6 +63,12 @@ for (var constructor of typedArrayConstructors) {
}
assertEquals(-1, array.indexOf(NaN));
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.indexOf(tmp), TypeError);
// ----------------------------------------------------------------------
// %TypedArray%.prototype.lastIndexOf.
// ----------------------------------------------------------------------
@ -89,4 +105,9 @@ for (var constructor of typedArrayConstructors) {
assertEquals(-1, array.lastIndexOf(-Infinity));
}
assertEquals(-1, array.lastIndexOf(NaN));
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.lastIndexOf(tmp), TypeError);
}

View File

@ -4,6 +4,8 @@
// Tests for standard TypedArray array iteration functions.
// Flags: --allow-natives-syntax
var typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -77,6 +79,11 @@ for (var constructor of typedArrayConstructors) {
assertArrayLikeEquals([2], a.filter(function(elt) {
return elt == 2;
}), constructor);
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.filter(() => false), TypeError);
})();
(function TypedArrayMapTest() {
@ -130,6 +137,11 @@ for (var constructor of typedArrayConstructors) {
return NaN;
}), constructor);
}
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.map((v) => v), TypeError);
})();
//
@ -189,6 +201,11 @@ for (var constructor of typedArrayConstructors) {
assertEquals(false, Array.prototype.some.call(a, function(elt) {
return elt == 2;
}));
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.some((v) => false), TypeError);
})();
}

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -247,4 +249,18 @@ for (var constructor of typedArrayConstructors) {
assertEquals(1, constructor.prototype.reduce.length);
assertEquals(1, constructor.prototype.reduceRight.length);
// Detached Operation
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.reduce(sum, tmp), TypeError);
assertThrows(() => array.reduceRight(sum, tmp), TypeError);
}

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function ArrayMaker(x) {
return x;
}
@ -51,4 +53,11 @@ for (var constructor of arrayConstructors) {
}
assertEquals(0, a.reverse.length);
// Detached Operation
if (constructor != ArrayMaker) {
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.reverse(), TypeError);
}
}

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -69,6 +71,19 @@ for (var constructor of typedArrayConstructors) {
assertEquals(3, slice[1]);
assertTrue(slice instanceof constructor);
// Detached Operation
var tmp = {
[Symbol.toPrimitive]() {
assertUnreachable("Parameter should not be processed when " +
"array.[[ViewedArrayBuffer]] is neutered.");
return 0;
}
};
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.slice(tmp, tmp), TypeError);
// Check that the species array must be a typed array
class MyTypedArray extends constructor {
static get[Symbol.species]() {

View File

@ -2,6 +2,8 @@
// 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 typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -60,4 +62,9 @@ for (var constructor of typedArrayConstructors) {
b[0] = 3; b[1] = 2; b[2] = 1;
a.sort();
assertArrayLikeEquals(a, [1, 2], constructor);
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.sort(), TypeError);
}

View File

@ -5,6 +5,8 @@
// Array's toString should call the object's own join method, if one exists and
// is callable. Otherwise, just use the original Object.toString function.
// Flags: --allow-natives-syntax
var typedArrayConstructors = [
Uint8Array,
Int8Array,
@ -96,4 +98,11 @@ for (var constructor of typedArrayConstructors) {
Number.prototype.toLocaleString = NumberToLocaleString;
})();
// Detached Operation
var array = new constructor([1, 2, 3]);
%ArrayBufferNeuter(array.buffer);
assertThrows(() => array.join(), TypeError);
assertThrows(() => array.toLocalString(), TypeError);
assertThrows(() => array.toString(), TypeError);
}

View File

@ -59,18 +59,18 @@ assertThrows(function() {
var buffer9 = new ArrayBuffer(1024);
var array9 = new Uint8Array(buffer9);
var array10 = array9.subarray({valueOf : function() {
assertThrows(() =>
array9.subarray({valueOf : function() {
%ArrayBufferNeuter(buffer9);
return 0;
}}, 1024);
}}, 1024), TypeError);
assertEquals(0, array9.length);
assertEquals(0, array10.length);
var buffer11 = new ArrayBuffer(1024);
var array11 = new Uint8Array(buffer11);
var array12 = array11.subarray(0, {valueOf : function() {
%ArrayBufferNeuter(buffer11);
return 1024;
}});
assertThrows(() =>
array11.subarray(0, {valueOf : function() {
%ArrayBufferNeuter(buffer11);
return 1024;
}}), TypeError);
assertEquals(0, array11.length);
assertEquals(0, array12.length);

View File

@ -11,12 +11,14 @@ FirstBuffer.__proto__ = Uint8Array
var buf = new Uint8Array(10)
buf.__proto__ = FirstBuffer.prototype
var buf2 = buf.subarray(2)
assertEquals(8, buf2.length);
assertThrows(() => buf.subarray(2), TypeError);
// Second test case
let seen_args = [];
function SecondBuffer (arg) {
seen_args.push(arg);
var arr = new Uint8Array(arg)
arr.__proto__ = SecondBuffer.prototype
return arr
@ -25,7 +27,9 @@ SecondBuffer.prototype.__proto__ = Uint8Array.prototype
SecondBuffer.__proto__ = Uint8Array
var buf3 = new SecondBuffer(10)
assertEquals([10], seen_args);
var buf4 = buf3.subarray(2)
assertEquals(8, buf4.length);
assertEquals(10, buf4.length);
assertEquals([10, buf3.buffer], seen_args);

View File

@ -112,7 +112,6 @@
'built-ins/TypedArray/prototype/slice/detached-buffer-custom-ctor-other-targettype': [FAIL],
'built-ins/TypedArray/prototype/slice/detached-buffer-custom-ctor-same-targettype': [FAIL],
'built-ins/TypedArray/prototype/slice/detached-buffer-get-ctor': [FAIL],
'built-ins/TypedArray/prototype/slice/detached-buffer-speciesctor-get-species-custom-ctor-throws': [FAIL],
'built-ins/TypedArray/prototype/some/callbackfn-detachbuffer': [FAIL],
'built-ins/TypedArray/prototype/sort/detached-buffer-comparefn': [FAIL],
# DataView functions should also throw on detached buffers
@ -153,27 +152,6 @@
'built-ins/DataView/prototype/setUint8/detached-buffer': [FAIL],
'built-ins/DataView/prototype/setUint8/detached-buffer-before-outofrange-byteoffset': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4648
'built-ins/TypedArray/prototype/copyWithin/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/every/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/fill/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/filter/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/find/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/findIndex/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/forEach/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/includes/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/indexOf/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/join/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/lastIndexOf/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/map/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/reverse/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/slice/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/some/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/sort/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/subarray/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/toLocaleString/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/toString/detached-buffer': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4034
'built-ins/ThrowTypeError/unique-per-realm-function-proto': [FAIL],
@ -547,19 +525,6 @@
# https://code.google.com/p/v8/issues/detail?id=4693
'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-function-declaration': [PASS, FAIL_SLOPPY],
# https://bugs.chromium.org/p/v8/issues/detail?id=4953
'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-abrupt': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-inherited': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-returns-throws': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-abrupt': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-returns-another-instance': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-throws': [FAIL],
'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-returns-throws': [FAIL],
# We do not expose Array.prototype.values due to webcompat issues.
# Most recent incompatability: https://crbug.com/615873
# https://code.google.com/p/v8/issues/detail?id=4247