Commit 2bd9bdbe authored by littledan's avatar littledan Committed by Commit bot

TypedArray and ArrayBuffer support for @@species

This patch improves ArrayBuffer and TypedArray subclassing by adding
support for @@species and constructing outputs to certain methods
by creating an instance of the constructor determined by the
SpeciesConstructor algorithm, rather than fixed to a superclass or
naively the constructor. The new behavior is enabled by the
--harmony-species flag. Care is taken to not significantly change the
observable behavior when the flag is off. Previously, TypedArrays
already supported subclassing by reading the constructor of the
receiver, but ArrayBuffers did not, and this old behavior is
preserved and tested for, to avoid a multi-stage upgrade path and keep
things simple for users.

R=adamk
BUG=v8:4093
LOG=Y

Review URL: https://codereview.chromium.org/1574903004

Cr-Commit-Position: refs/heads/master@{#33223}
parent b37e7861
......@@ -15,11 +15,13 @@ var GlobalArrayBuffer = global.ArrayBuffer;
var MakeTypeError;
var MaxSimple;
var MinSimple;
var SpeciesConstructor;
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
MaxSimple = from.MaxSimple;
MinSimple = from.MinSimple;
SpeciesConstructor = from.SpeciesConstructor;
});
// -------------------------------------------------------------------
......@@ -62,10 +64,21 @@ function ArrayBufferSlice(start, end) {
fin = first;
}
var newLen = fin - first;
// TODO(dslomov): implement inheritance
var result = new GlobalArrayBuffer(newLen);
var constructor = SpeciesConstructor(this, GlobalArrayBuffer, true);
var result = new constructor(newLen);
if (!IS_ARRAYBUFFER(result)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
'ArrayBuffer.prototype.slice', result);
}
// TODO(littledan): Check for a detached ArrayBuffer
if (result === this) {
throw MakeTypeError(kArrayBufferSpeciesThis);
}
if (%_ArrayBufferGetByteLength(result) < newLen) {
throw MakeTypeError(kArrayBufferTooShort);
}
%ArrayBufferSliceImpl(this, result, first);
%ArrayBufferSliceImpl(this, result, first, newLen);
return result;
}
......
......@@ -16,15 +16,22 @@
%CheckIsBootstrapping();
var FLAG_harmony_species;
var GlobalArray = global.Array;
var GlobalBoolean = global.Boolean;
var GlobalString = global.String;
var isConcatSpreadableSymbol =
utils.ImportNow("is_concat_spreadable_symbol");
var MakeRangeError;
var MakeTypeError;
var speciesSymbol;
utils.Import(function(from) {
MakeRangeError = from.MakeRangeError;
MakeTypeError = from.MakeTypeError;
speciesSymbol = from.species_symbol;
});
utils.ImportFromExperimental(function(from) {
FLAG_harmony_species = from.FLAG_harmony_species;
});
// ----------------------------------------------------------------------------
......@@ -118,6 +125,39 @@ function MinSimple(a, b) {
%SetForceInlineFlag(MaxSimple);
%SetForceInlineFlag(MinSimple);
// ES2015 7.3.20
// For the fallback with --harmony-species off, there are two possible choices:
// - "conservative": return defaultConstructor
// - "not conservative": return object.constructor
// This fallback path is only needed in the transition to ES2015, and the
// choice is made simply to preserve the previous behavior so that we don't
// have a three-step upgrade: old behavior, unspecified intermediate behavior,
// and ES2015.
// In some cases, we were "conservative" (e.g., ArrayBuffer, RegExp), and in
// other cases we were "not conservative (e.g., TypedArray, Promise).
function SpeciesConstructor(object, defaultConstructor, conservative) {
if (FLAG_harmony_species) {
var constructor = object.constructor;
if (IS_UNDEFINED(constructor)) {
return defaultConstructor;
}
if (!IS_RECEIVER(constructor)) {
throw MakeTypeError(kConstructorNotReceiver);
}
var species = constructor[speciesSymbol];
if (IS_NULL_OR_UNDEFINED(species)) {
return defaultConstructor;
}
if (%IsConstructor(species)) {
return species;
}
throw MakeTypeError(kSpeciesNotConstructor);
} else {
return conservative ? defaultConstructor : object.constructor;
}
}
//----------------------------------------------------------------------------
// NOTE: Setting the prototype for Array must take place as early as
......@@ -137,6 +177,7 @@ utils.Export(function(to) {
to.SameValue = SameValue;
to.SameValueZero = SameValueZero;
to.ToPositiveInteger = ToPositiveInteger;
to.SpeciesConstructor = SpeciesConstructor;
});
%InstallToContext([
......
......@@ -18,6 +18,7 @@ var GlobalArray = global.Array;
var GlobalArrayBuffer = global.ArrayBuffer;
var GlobalDataView = global.DataView;
var GlobalObject = global.Object;
var InternalArray = utils.InternalArray;
var InnerArrayCopyWithin;
var InnerArrayEvery;
var InnerArrayFill;
......@@ -41,6 +42,7 @@ var MakeTypeError;
var MaxSimple;
var MinSimple;
var PackedArrayReverse;
var SpeciesConstructor;
var ToPositiveInteger;
var iteratorSymbol = utils.ImportNow("iterator_symbol");
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
......@@ -87,17 +89,51 @@ utils.Import(function(from) {
IsNaN = from.IsNaN;
MakeRangeError = from.MakeRangeError;
MakeTypeError = from.MakeTypeError;
MakeTypeError = from.MakeTypeError;
MaxSimple = from.MaxSimple;
MaxSimple = from.MaxSimple;
MinSimple = from.MinSimple;
MinSimple = from.MinSimple;
PackedArrayReverse = from.PackedArrayReverse;
SpeciesConstructor = from.SpeciesConstructor;
ToPositiveInteger = from.ToPositiveInteger;
});
// --------------- Typed Arrays ---------------------
function TypedArrayDefaultConstructor(typedArray) {
switch (%_ClassOf(typedArray)) {
macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
case "NAME":
return GlobalNAME;
endmacro
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
}
// The TypeError should not be generated since all callers should
// have already called ValidateTypedArray.
throw MakeTypeError(kIncompatibleMethodReceiver,
"TypedArrayDefaultConstructor", this);
}
function TypedArrayCreate(constructor, arg0, arg1, arg2) {
if (IS_UNDEFINED(arg1)) {
var newTypedArray = new constructor(arg0);
} else {
var newTypedArray = new constructor(arg0, arg1, arg2);
}
if (!%_IsTypedArray(newTypedArray)) throw MakeTypeError(kNotTypedArray);
// TODO(littledan): Check for being detached, here and elsewhere
// All callers where the first argument is a Number have no additional
// arguments.
if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
throw MakeTypeError(kTypedArrayTooShort);
}
return newTypedArray;
}
function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2) {
var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
var constructor = SpeciesConstructor(exemplar, defaultConstructor);
return TypedArrayCreate(constructor, arg0, arg1, arg2);
}
macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
if (!IS_UNDEFINED(byteOffset)) {
......@@ -210,6 +246,10 @@ function NAMEConstructor(arg1, arg2, arg3) {
IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
NAMEConstructByLength(this, arg1);
} else {
// TODO(littledan): If arg1 is a TypedArray, follow the constructor
// path in ES2015 22.2.4.3, and call SpeciesConstructor, in a
// path that seems to be an optimized version of what's below, but
// in an observably different way.
var iteratorFn = arg1[iteratorSymbol];
if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
NAMEConstructByArrayLike(this, arg1);
......@@ -251,8 +291,8 @@ function NAMESubArray(begin, end) {
var newLength = endInt - beginInt;
var beginByteOffset =
%_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
return new GlobalNAME(%TypedArrayGetBuffer(this),
beginByteOffset, newLength);
return TypedArraySpeciesCreate(this, %TypedArrayGetBuffer(this),
beginByteOffset, newLength);
}
endmacro
......@@ -420,32 +460,6 @@ function TypedArrayGetToStringTag() {
}
function ConstructTypedArray(constructor, arg) {
// TODO(littledan): This is an approximation of the spec, which requires
// that only real TypedArray classes should be accepted (22.2.2.1.1)
if (!%IsConstructor(constructor) || IS_UNDEFINED(constructor.prototype) ||
!%HasOwnProperty(constructor.prototype, "BYTES_PER_ELEMENT")) {
throw MakeTypeError(kNotTypedArray);
}
// TODO(littledan): The spec requires that, rather than directly calling
// the constructor, a TypedArray is created with the proper proto and
// underlying size and element size, and elements are put in one by one.
// By contrast, this would allow subclasses to make a radically different
// constructor with different semantics.
return new constructor(arg);
}
function ConstructTypedArrayLike(typedArray, arg) {
// TODO(littledan): The spec requires that we actuallly use
// typedArray.constructor[Symbol.species] (bug v8:4093)
// Also, it should default to the default constructor from
// table 49 if typedArray.constructor doesn't exist.
return ConstructTypedArray(typedArray.constructor, arg);
}
function TypedArrayCopyWithin(target, start, end) {
if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
......@@ -499,7 +513,7 @@ function TypedArrayFilter(f, thisArg) {
var result = new InternalArray();
InnerArrayFilter(f, thisArg, this, length, result);
var captured = result.length;
var output = ConstructTypedArrayLike(this, captured);
var output = TypedArraySpeciesCreate(this, captured);
for (var i = 0; i < captured; i++) {
output[i] = result[i];
}
......@@ -601,7 +615,7 @@ function TypedArrayMap(f, thisArg) {
if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
var length = %_TypedArrayGetLength(this);
var result = ConstructTypedArrayLike(this, length);
var result = TypedArraySpeciesCreate(this, length);
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
for (var i = 0; i < length; i++) {
var element = this[i];
......@@ -699,15 +713,13 @@ function TypedArraySlice(start, end) {
}
var count = MaxSimple(final - k, 0);
var array = ConstructTypedArrayLike(this, count);
var array = TypedArraySpeciesCreate(this, count);
// The code below is the 'then' branch; the 'else' branch species
// a memcpy. Because V8 doesn't canonicalize NaN, the difference is
// unobservable.
var n = 0;
while (k < final) {
var kValue = this[k];
// TODO(littledan): The spec says to throw on an error in setting;
// does this throw?
array[n] = kValue;
k++;
n++;
......@@ -730,7 +742,7 @@ function TypedArrayIncludes(searchElement, fromIndex) {
// ES6 draft 08-24-14, section 22.2.2.2
function TypedArrayOf() {
var length = %_ArgumentsLength();
var array = new this(length);
var array = TypedArrayCreate(this, length);
for (var i = 0; i < length; i++) {
array[i] = %_Arguments(i);
}
......@@ -741,8 +753,11 @@ function TypedArrayOf() {
function TypedArrayFrom(source, mapfn, thisArg) {
// TODO(littledan): Investigate if there is a receiver which could be
// faster to accumulate on than Array, e.g., a TypedVector.
// TODO(littledan): Rewrite this code to ensure that things happen
// in the right order, e.g., the constructor needs to be called before
// the mapping function on array-likes.
var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg);
return ConstructTypedArray(this, array);
return TypedArrayCreate(this, array);
}
%FunctionSetLength(TypedArrayFrom, 1);
......
......@@ -87,6 +87,10 @@ class CallSite {
T(ApplyNonFunction, \
"Function.prototype.apply was called on %, which is a % and not a " \
"function") \
T(ArrayBufferTooShort, \
"Derived ArrayBuffer constructor created a buffer which was too small") \
T(ArrayBufferSpeciesThis, \
"ArrayBuffer subclass returned this from species constructor") \
T(ArrayFunctionsOnFrozen, "Cannot modify frozen array elements") \
T(ArrayFunctionsOnSealed, "Cannot add/remove sealed array elements") \
T(ArrayNotSubclassable, "Subclassing Arrays is not currently supported.") \
......@@ -105,6 +109,7 @@ class CallSite {
T(ConstructorNonCallable, \
"Class constructor % cannot be invoked without 'new'") \
T(ConstructorNotFunction, "Constructor % requires 'new'") \
T(ConstructorNotReceiver, "The .constructor property is not an object") \
T(CurrencyCode, "Currency code is required with currency style.") \
T(DataViewNotArrayBuffer, \
"First argument to DataView constructor must be an ArrayBuffer") \
......@@ -291,7 +296,7 @@ class CallSite {
"'caller' and 'arguments' are restricted function properties and cannot " \
"be accessed in this context.") \
T(StaticPrototype, "Classes may not have static property named prototype") \
T(StrictCannotAssign, "Cannot assign to read only '% in strict mode") \
T(StrictCannotAssign, "Cannot assign to read only '%' in strict mode") \
T(StrictDeleteProperty, "Cannot delete property '%' of %") \
T(StrictPoisonPill, \
"'caller', 'callee', and 'arguments' properties may not be accessed on " \
......@@ -487,6 +492,8 @@ class CallSite {
T(TooManyParameters, \
"Too many parameters in function definition (only 65535 allowed)") \
T(TooManyVariables, "Too many variables declared (only 4194303 allowed)") \
T(TypedArrayTooShort, \
"Derived TypedArray constructor created an array which was too small") \
T(UnexpectedEOS, "Unexpected end of input") \
T(UnexpectedReserved, "Unexpected reserved word") \
T(UnexpectedStrictReserved, "Unexpected strict mode reserved word") \
......
......@@ -23,14 +23,16 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
RUNTIME_ASSERT(!source.is_identical_to(target));
size_t start = 0;
size_t start = 0, target_length = 0;
RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
size_t target_length = NumberToSize(isolate, target->byte_length());
RUNTIME_ASSERT(TryNumberToSize(isolate, *new_length, &target_length));
RUNTIME_ASSERT(NumberToSize(isolate, target->byte_length()) >= target_length);
if (target_length == 0) return isolate->heap()->undefined_value();
......
......@@ -971,7 +971,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferSliceImpl, 3, 1) \
F(ArrayBufferSliceImpl, 4, 1) \
F(ArrayBufferNeuter, 1, 1) \
F(TypedArrayInitialize, 6, 1) \
F(TypedArrayInitializeFromArrayLike, 4, 1) \
......
// Copyright 2015 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: --noharmony-species
// Before Symbol.species was added, ArrayBuffer subclasses constructed
// ArrayBuffers, and Array subclasses constructed Arrays, but TypedArray and
// Promise subclasses constructed an instance of the subclass.
'use strict';
assertEquals(undefined, Symbol.species);
class MyArray extends Array { }
let myArray = new MyArray();
assertEquals(MyArray, myArray.constructor);
assertEquals(Array, myArray.map(x => x + 1).constructor);
assertEquals(Array, myArray.concat().constructor);
class MyUint8Array extends Uint8Array { }
Object.defineProperty(MyUint8Array.prototype, "BYTES_PER_ELEMENT", {value: 1});
let myTypedArray = new MyUint8Array(3);
assertEquals(MyUint8Array, myTypedArray.constructor);
assertEquals(MyUint8Array, myTypedArray.map(x => x + 1).constructor);
class MyArrayBuffer extends ArrayBuffer { }
let myBuffer = new MyArrayBuffer(0);
assertEquals(MyArrayBuffer, myBuffer.constructor);
assertEquals(ArrayBuffer, myBuffer.slice().constructor);
class MyPromise extends Promise { }
let myPromise = new MyPromise(() => {});
assertEquals(MyPromise, myPromise.constructor);
assertEquals(MyPromise, myPromise.then().constructor);
......@@ -4,6 +4,8 @@
// Based on Mozilla Array.of() tests at http://dxr.mozilla.org/mozilla-central/source/js/src/jit-test/tests/collections
'use strict';
var typedArrayConstructors = [
Uint8Array,
Int8Array,
......@@ -51,28 +53,29 @@ function TestTypedArrayOf(constructor) {
assertEquals(aux.length, a.length);
assertArrayEquals(aux, a);
// %TypedArray%.of can be transplanted to other constructors.
// %TypedArray%.of can be called on subclasses of TypedArrays
var hits = 0;
function Bag(length) {
assertEquals(arguments.length, 1);
assertEquals(length, 2);
this.length = length;
hits++;
class Bag extends constructor {
constructor(length) {
super(length);
assertEquals(arguments.length, 1);
assertEquals(length, 2);
hits++;
}
}
Bag.of = constructor.of;
hits = 0;
a = Bag.of("zero", "one");
a = Bag.of(5, 6);
assertEquals(1, hits);
assertEquals(2, a.length);
assertArrayEquals(["zero", "one"], a);
assertArrayEquals([5, 6], a);
assertEquals(Bag.prototype, a.__proto__);
hits = 0;
actual = constructor.of.call(Bag, "zero", "one");
var actual = constructor.of.call(Bag, 5, 6);
assertEquals(1, hits);
assertEquals(2, a.length);
assertArrayEquals(["zero", "one"], a);
assertArrayEquals([5, 6], a);
assertEquals(Bag.prototype, a.__proto__);
// %TypedArray%.of does not trigger prototype setters.
......@@ -90,22 +93,23 @@ function TestTypedArrayOf(constructor) {
// invoked.
// Setter on the newly created object.
function Pack() {
Object.defineProperty(this, "length", {
set: function (v) { status = "fail"; }
});
class Pack extends constructor {
constructor(length) {
super(length);
Object.defineProperty(this, "length", {
set: function (v) { status = "fail"; }
});
}
}
Pack.of = constructor.of;
var pack = Pack.of("wolves", "cards", "cigarettes", "lies");
var pack = Pack.of(5, 6, 7, 8);
assertEquals("pass", status);
// when the setter is on the new object's prototype
function Bevy() {}
class Bevy extends constructor {}
Object.defineProperty(Bevy.prototype, "length", {
set: function (v) { status = "fail"; }
});
Bevy.of = constructor.of;
var bevy = Bevy.of("quail");
var bevy = Bevy.of(3);
assertEquals("pass", status);
// Check superficial features of %TypedArray%.of.
......
// Copyright 2015 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-species
// ArrayBuffer.prototype.slice makes subclass and checks length
class MyArrayBuffer extends ArrayBuffer { }
assertEquals(MyArrayBuffer, new MyArrayBuffer(0).slice().constructor);
class MyShortArrayBuffer extends ArrayBuffer {
constructor(length) { super(length - 1); }
}
assertThrows(() => new MyShortArrayBuffer(5).slice(0, 4), TypeError);
class SingletonArrayBuffer extends ArrayBuffer {
constructor(...args) {
if (SingletonArrayBuffer.cached) return SingletonArrayBuffer.cached;
super(...args);
SingletonArrayBuffer.cached = this;
}
}
assertThrows(() => new SingletonArrayBuffer(5).slice(0, 4), TypeError);
class NonArrayBuffer extends ArrayBuffer {
constructor() {
return {};
}
}
assertThrows(() => new NonArrayBuffer(5).slice(0, 4), TypeError);
// Species fallback is ArrayBuffer
class UndefinedArrayBuffer extends ArrayBuffer { }
UndefinedArrayBuffer.prototype.constructor = undefined;
assertEquals(ArrayBuffer, new UndefinedArrayBuffer(0).slice().constructor);
// Copyright 2015 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-species
// Subclasses of %TypedArray% construct themselves under map, etc
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array
];
for (let constructor of typedArrayConstructors) {
class MyTypedArray extends constructor { }
assertEquals(MyTypedArray, new MyTypedArray().map(()=>0).constructor);
assertEquals(MyTypedArray, new MyTypedArray().filter(()=>{}).constructor);
assertEquals(MyTypedArray, new MyTypedArray().slice().constructor);
}
// Subclasses can override @@species to return the another class
for (let constructor of typedArrayConstructors) {
class MyTypedArray extends constructor { }
class MyOtherTypedArray extends constructor {
static get [Symbol.species]() { return MyTypedArray; }
}
assertEquals(MyTypedArray, new MyOtherTypedArray().map(()=>0).constructor);
assertEquals(MyTypedArray, new MyOtherTypedArray().filter(()=>{}).constructor);
assertEquals(MyTypedArray, new MyOtherTypedArray().slice().constructor);
}
// TypedArray too-short and non-TypedArray error checking
for (let constructor of typedArrayConstructors) {
class MyShortTypedArray extends constructor {
constructor(length) { super(length - 1); }
}
assertThrows(() => new MyShortTypedArray(5).map(()=>0), TypeError);
assertThrows(() => new MyShortTypedArray(5).filter(()=>true), TypeError);
assertThrows(() => new MyShortTypedArray(5).slice(), TypeError);
class MyNonTypedArray extends constructor {
static get [Symbol.species]() { return Array; }
}
assertThrows(() => new MyNonTypedArray().map(()=>0), TypeError);
assertThrows(() => new MyNonTypedArray().filter(()=>{}), TypeError);
assertThrows(() => new MyNonTypedArray().slice(), TypeError);
}
// Defaults when constructor or @@species is missing or non-constructor
for (let constructor of typedArrayConstructors) {
class MyDefaultTypedArray extends constructor {
static get [Symbol.species]() { return undefined; }
}
assertEquals(constructor, new MyDefaultTypedArray().map(()=>0).constructor);
class MyOtherDefaultTypedArray extends constructor { }
assertEquals(MyOtherDefaultTypedArray, new MyOtherDefaultTypedArray().map(()=>0).constructor);
MyOtherDefaultTypedArray.prototype.constructor = undefined;
assertEquals(constructor, new MyOtherDefaultTypedArray().map(()=>0).constructor);
}
// Exceptions propagated when getting constructor @@species throws
class SpeciesError extends Error { }
class ConstructorError extends Error { }
for (let constructor of typedArrayConstructors) {
class MyThrowingArray extends constructor {
static get [Symbol.species]() { throw new SpeciesError; }
}
assertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError);
Object.defineProperty(MyThrowingArray.prototype, 'constructor', {
get() { throw new ConstructorError; }
});
assertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError);
}
......@@ -55,10 +55,6 @@
'es6/debug-promises/reject-with-undefined-reject': [FAIL],
'es6/debug-promises/reject-with-invalid-reject': [FAIL],
# Issue 4093: This test will be updated in the course of implementing
# @@species, when TypedArray support is added.
'regress/regress-544991': [SKIP],
##############################################################################
# TurboFan compiler failures.
......@@ -998,6 +994,7 @@
'regress/regress-520029': [SKIP],
'regress/regress-542099': [SKIP],
'regress/regress-542100': [SKIP],
'regress/regress-544991': [SKIP],
'regress/regress-568765': [SKIP],
'regress/regress-580': [SKIP],
'regress/regress-618': [SKIP],
......
......@@ -2,14 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-species
'use strict';
var typedArray = new Int8Array(1);
var saved;
var called;
typedArray.constructor = function(x) { called = true; saved = x };
typedArray.constructor.prototype = Int8Array.prototype;
class TypedArraySubclass extends Int8Array {
constructor(x) {
super(x);
called = true;
saved = x;
}
}
typedArray.constructor = TypedArraySubclass
typedArray.map(function(){});
// To meet the spec, constructor shouldn't be called directly, but
// if it is called for now, the argument should be an Array
assertTrue(called); // Will fail later; when so, delete this test
assertEquals("Array", saved.constructor.name);
assertTrue(called);
assertEquals(saved, 1);
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