1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 17425bb815Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 18425bb815Sopenharmony_ci// found in the LICENSE file. 19425bb815Sopenharmony_ci 20425bb815Sopenharmony_ci// Test the ES2015 @@species feature 21425bb815Sopenharmony_ci 22425bb815Sopenharmony_ci'use strict'; 23425bb815Sopenharmony_ci 24425bb815Sopenharmony_ci// Subclasses of Array construct themselves under map, etc 25425bb815Sopenharmony_ci 26425bb815Sopenharmony_ciclass MyArray extends Array { } 27425bb815Sopenharmony_ci 28425bb815Sopenharmony_cifunction assertEquals(a, b) { 29425bb815Sopenharmony_ci assert(a === b); 30425bb815Sopenharmony_ci} 31425bb815Sopenharmony_ci 32425bb815Sopenharmony_ciassertEquals(MyArray, new MyArray().map(()=>{}).constructor); 33425bb815Sopenharmony_ciassertEquals(MyArray, new MyArray().filter(()=>{}).constructor); 34425bb815Sopenharmony_ciassertEquals(MyArray, new MyArray().slice().constructor); 35425bb815Sopenharmony_ciassertEquals(MyArray, new MyArray().splice().constructor); 36425bb815Sopenharmony_ciassertEquals(MyArray, new MyArray().concat([1]).constructor); 37425bb815Sopenharmony_ciassertEquals(1, new MyArray().concat([1])[0]); 38425bb815Sopenharmony_ci 39425bb815Sopenharmony_ci// Subclasses can override @@species to return the another class 40425bb815Sopenharmony_ci 41425bb815Sopenharmony_ciclass MyOtherArray extends Array { 42425bb815Sopenharmony_ci static get [Symbol.species]() { return MyArray; } 43425bb815Sopenharmony_ci} 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ciassertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor); 46425bb815Sopenharmony_ciassertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor); 47425bb815Sopenharmony_ciassertEquals(MyArray, new MyOtherArray().slice().constructor); 48425bb815Sopenharmony_ciassertEquals(MyArray, new MyOtherArray().splice().constructor); 49425bb815Sopenharmony_ciassertEquals(MyArray, new MyOtherArray().concat().constructor); 50425bb815Sopenharmony_ci 51425bb815Sopenharmony_ci// Array methods on non-arrays return arrays 52425bb815Sopenharmony_ci 53425bb815Sopenharmony_ciclass MyNonArray extends Array { 54425bb815Sopenharmony_ci static get [Symbol.species]() { return MyObject; } 55425bb815Sopenharmony_ci} 56425bb815Sopenharmony_ci 57425bb815Sopenharmony_ciclass MyObject { } 58425bb815Sopenharmony_ci 59425bb815Sopenharmony_ciassertEquals(MyObject, 60425bb815Sopenharmony_ci Array.prototype.map.call(new MyNonArray(), ()=>{}).constructor); 61425bb815Sopenharmony_ciassertEquals(MyObject, 62425bb815Sopenharmony_ci Array.prototype.filter.call(new MyNonArray(), ()=>{}).constructor); 63425bb815Sopenharmony_ciassertEquals(MyObject, 64425bb815Sopenharmony_ci Array.prototype.slice.call(new MyNonArray()).constructor); 65425bb815Sopenharmony_ciassertEquals(MyObject, 66425bb815Sopenharmony_ci Array.prototype.splice.call(new MyNonArray()).constructor); 67425bb815Sopenharmony_ciassertEquals(MyObject, 68425bb815Sopenharmony_ci Array.prototype.concat.call(new MyNonArray()).constructor); 69425bb815Sopenharmony_ci 70425bb815Sopenharmony_ciassertEquals(undefined, 71425bb815Sopenharmony_ci Array.prototype.map.call(new MyNonArray(), ()=>{}).length); 72425bb815Sopenharmony_ciassertEquals(undefined, 73425bb815Sopenharmony_ci Array.prototype.filter.call(new MyNonArray(), ()=>{}).length); 74425bb815Sopenharmony_ci// slice, splice, and concat actually do explicitly define the length. 75425bb815Sopenharmony_ciassertEquals(0, Array.prototype.slice.call(new MyNonArray()).length); 76425bb815Sopenharmony_ciassertEquals(0, Array.prototype.splice.call(new MyNonArray()).length); 77425bb815Sopenharmony_ciassertEquals(1, Array.prototype.concat.call(new MyNonArray(), ()=>{}).length); 78425bb815Sopenharmony_ci 79425bb815Sopenharmony_ci// Defaults when constructor or @@species is missing or non-constructor 80425bb815Sopenharmony_ci 81425bb815Sopenharmony_ciclass MyDefaultArray extends Array { 82425bb815Sopenharmony_ci static get [Symbol.species]() { return undefined; } 83425bb815Sopenharmony_ci} 84425bb815Sopenharmony_ciassertEquals(Array, new MyDefaultArray().map(()=>{}).constructor); 85425bb815Sopenharmony_ci 86425bb815Sopenharmony_ciclass MyOtherDefaultArray extends Array { } 87425bb815Sopenharmony_ciassertEquals(MyOtherDefaultArray, 88425bb815Sopenharmony_ci new MyOtherDefaultArray().map(()=>{}).constructor); 89425bb815Sopenharmony_ciMyOtherDefaultArray.prototype.constructor = undefined; 90425bb815Sopenharmony_ciassertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor); 91425bb815Sopenharmony_ciassertEquals(Array, new MyOtherDefaultArray().concat().constructor); 92425bb815Sopenharmony_ci 93425bb815Sopenharmony_ci// Exceptions propagated when getting constructor @@species throws 94425bb815Sopenharmony_ci 95425bb815Sopenharmony_ciclass SpeciesError extends Error { } 96425bb815Sopenharmony_ciclass ConstructorError extends Error { } 97425bb815Sopenharmony_ciclass MyThrowingArray extends Array { 98425bb815Sopenharmony_ci static get [Symbol.species]() { throw new SpeciesError; } 99425bb815Sopenharmony_ci} 100425bb815Sopenharmony_ci 101425bb815Sopenharmony_cifunction assertThrows (a, b) { 102425bb815Sopenharmony_ci try { 103425bb815Sopenharmony_ci a(); 104425bb815Sopenharmony_ci } catch (e) { 105425bb815Sopenharmony_ci assert(e instanceof b); 106425bb815Sopenharmony_ci } 107425bb815Sopenharmony_ci} 108425bb815Sopenharmony_ci 109425bb815Sopenharmony_ciassertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError); 110425bb815Sopenharmony_ciObject.defineProperty(MyThrowingArray.prototype, 'constructor', { 111425bb815Sopenharmony_ci get() { throw new ConstructorError; } 112425bb815Sopenharmony_ci}); 113425bb815Sopenharmony_ciassertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError); 114425bb815Sopenharmony_ci 115425bb815Sopenharmony_ci// Previously unexpected errors from setting properties in arrays throw 116425bb815Sopenharmony_ci 117425bb815Sopenharmony_ciclass FrozenArray extends Array { 118425bb815Sopenharmony_ci constructor(...args) { 119425bb815Sopenharmony_ci super(...args); 120425bb815Sopenharmony_ci Object.freeze(this); 121425bb815Sopenharmony_ci } 122425bb815Sopenharmony_ci} 123425bb815Sopenharmony_ciassertThrows(() => new FrozenArray([1]).map(()=>0), TypeError); 124425bb815Sopenharmony_ciassertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError); 125425bb815Sopenharmony_ciassertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError); 126425bb815Sopenharmony_ciassertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError); 127425bb815Sopenharmony_ciassertThrows(() => new FrozenArray([]).concat([1]), TypeError); 128425bb815Sopenharmony_ci 129425bb815Sopenharmony_ci// Verify call counts and constructor parameters 130425bb815Sopenharmony_ci 131425bb815Sopenharmony_civar count; 132425bb815Sopenharmony_civar params; 133425bb815Sopenharmony_ciclass MyObservedArray extends Array { 134425bb815Sopenharmony_ci constructor(...args) { 135425bb815Sopenharmony_ci super(...args); 136425bb815Sopenharmony_ci params = args; 137425bb815Sopenharmony_ci } 138425bb815Sopenharmony_ci static get [Symbol.species]() { 139425bb815Sopenharmony_ci count++ 140425bb815Sopenharmony_ci return this; 141425bb815Sopenharmony_ci } 142425bb815Sopenharmony_ci} 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_cifunction assertArrayEquals(value, expected, type) { 145425bb815Sopenharmony_ci assert(expected.length === value.length); 146425bb815Sopenharmony_ci for (var i=0; i<value.length; ++i) { 147425bb815Sopenharmony_ci assertEquals(expected[i], value[i]); 148425bb815Sopenharmony_ci } 149425bb815Sopenharmony_ci} 150425bb815Sopenharmony_ci 151425bb815Sopenharmony_cicount = 0; 152425bb815Sopenharmony_ciparams = undefined; 153425bb815Sopenharmony_ciassertEquals(MyObservedArray, 154425bb815Sopenharmony_ci new MyObservedArray().map(()=>{}).constructor); 155425bb815Sopenharmony_ciassertEquals(1, count); 156425bb815Sopenharmony_ciassertArrayEquals([0], params); 157425bb815Sopenharmony_ci 158425bb815Sopenharmony_cicount = 0; 159425bb815Sopenharmony_ciparams = undefined; 160425bb815Sopenharmony_ciassertEquals(MyObservedArray, 161425bb815Sopenharmony_ci new MyObservedArray().filter(()=>{}).constructor); 162425bb815Sopenharmony_ciassertEquals(1, count); 163425bb815Sopenharmony_ciassertArrayEquals([0], params); 164425bb815Sopenharmony_ci 165425bb815Sopenharmony_cicount = 0; 166425bb815Sopenharmony_ciparams = undefined; 167425bb815Sopenharmony_ciassertEquals(MyObservedArray, 168425bb815Sopenharmony_ci new MyObservedArray().concat().constructor); 169425bb815Sopenharmony_ciassertEquals(1, count); 170425bb815Sopenharmony_ciassertArrayEquals([0], params); 171425bb815Sopenharmony_ci 172425bb815Sopenharmony_cicount = 0; 173425bb815Sopenharmony_ciparams = undefined; 174425bb815Sopenharmony_ciassertEquals(MyObservedArray, 175425bb815Sopenharmony_ci new MyObservedArray().slice().constructor); 176425bb815Sopenharmony_ciassertEquals(1, count); 177425bb815Sopenharmony_ciassertArrayEquals([0], params); 178425bb815Sopenharmony_ci 179425bb815Sopenharmony_cicount = 0; 180425bb815Sopenharmony_ciparams = undefined; 181425bb815Sopenharmony_ciassertEquals(MyObservedArray, 182425bb815Sopenharmony_ci new MyObservedArray().splice().constructor); 183425bb815Sopenharmony_ciassertEquals(1, count); 184425bb815Sopenharmony_ciassertArrayEquals([0], params); 185