diff options
Diffstat (limited to 'deps/v8/test/mjsunit/harmony/array-species.js')
-rw-r--r-- | deps/v8/test/mjsunit/harmony/array-species.js | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/deps/v8/test/mjsunit/harmony/array-species.js b/deps/v8/test/mjsunit/harmony/array-species.js new file mode 100644 index 0000000000..75a45aaf59 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/array-species.js @@ -0,0 +1,156 @@ +// 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 --harmony-proxies + +// Test the ES2015 @@species feature + +'use strict'; + +// Subclasses of Array construct themselves under map, etc + +class MyArray extends Array { } + +assertEquals(MyArray, new MyArray().map(()=>{}).constructor); +assertEquals(MyArray, new MyArray().filter(()=>{}).constructor); +assertEquals(MyArray, new MyArray().slice().constructor); +assertEquals(MyArray, new MyArray().splice().constructor); + +// Subclasses can override @@species to return the another class + +class MyOtherArray extends Array { + static get [Symbol.species]() { return MyArray; } +} + +assertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor); +assertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor); +assertEquals(MyArray, new MyOtherArray().slice().constructor); +assertEquals(MyArray, new MyOtherArray().splice().constructor); + +// Array methods on non-arrays return arrays + +class MyNonArray extends Array { + static get [Symbol.species]() { return MyObject; } +} + +class MyObject { } + +assertEquals(MyObject, + Array.prototype.map.call(new MyNonArray(), ()=>{}).constructor); +assertEquals(MyObject, + Array.prototype.filter.call(new MyNonArray(), ()=>{}).constructor); +assertEquals(MyObject, + Array.prototype.slice.call(new MyNonArray()).constructor); +assertEquals(MyObject, + Array.prototype.splice.call(new MyNonArray()).constructor); + +assertEquals(undefined, + Array.prototype.map.call(new MyNonArray(), ()=>{}).length); +assertEquals(undefined, + Array.prototype.filter.call(new MyNonArray(), ()=>{}).length); +// slice and splice actually do explicitly define the length for some reason +assertEquals(0, Array.prototype.slice.call(new MyNonArray()).length); +assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length); + +// Cross-realm Arrays build same-realm arrays + +var realm = Realm.create(); +assertEquals(Array, + Array.prototype.map.call( + Realm.eval(realm, "[]"), ()=>{}).constructor); +assertFalse(Array === Realm.eval(realm, "[]").map(()=>{}).constructor); +assertFalse(Array === Realm.eval(realm, "[].map(()=>{}).constructor")); + +// Defaults when constructor or @@species is missing or non-constructor + +class MyDefaultArray extends Array { + static get [Symbol.species]() { return undefined; } +} +assertEquals(Array, new MyDefaultArray().map(()=>{}).constructor); + +class MyOtherDefaultArray extends Array { } +assertEquals(MyOtherDefaultArray, + new MyOtherDefaultArray().map(()=>{}).constructor); +MyOtherDefaultArray.prototype.constructor = undefined; +assertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor); + +// Exceptions propagated when getting constructor @@species throws + +class SpeciesError extends Error { } +class ConstructorError extends Error { } +class MyThrowingArray extends Array { + 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); + +// Previously unexpected errors from setting properties in arrays throw + +class FrozenArray extends Array { + constructor(...args) { + super(...args); + Object.freeze(this); + } +} +assertThrows(() => new FrozenArray([1]).map(()=>0), TypeError); +assertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError); +assertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError); +assertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError); + +// Verify call counts and constructor parameters + +var count; +var params; +class MyObservedArray extends Array { + constructor(...args) { + super(...args); + params = args; + } + static get [Symbol.species]() { + count++ + return this; + } +} + +count = 0; +params = undefined; +assertEquals(MyObservedArray, + new MyObservedArray().map(()=>{}).constructor); +assertEquals(1, count); +assertArrayEquals([0], params); + +count = 0; +params = undefined; +assertEquals(MyObservedArray, + new MyObservedArray().filter(()=>{}).constructor); +assertEquals(1, count); +assertArrayEquals([0], params); + +count = 0; +params = undefined; +assertEquals(MyObservedArray, + new MyObservedArray().slice().constructor); +// TODO(littledan): Should be 1 +assertEquals(2, count); +assertArrayEquals([0], params); + +count = 0; +params = undefined; +assertEquals(MyObservedArray, + new MyObservedArray().splice().constructor); +// TODO(littledan): Should be 1 +assertEquals(2, count); +assertArrayEquals([0], params); + +// @@species constructor can be a Proxy, and the realm access doesn't +// crash + +class MyProxyArray extends Array { } +let ProxyArray = new Proxy(MyProxyArray, {}); +MyProxyArray.constructor = ProxyArray; + +assertEquals(MyProxyArray, new ProxyArray().map(()=>{}).constructor); |