Commit 22be7843 authored by littledan's avatar littledan Committed by Commit bot

Support @@species in Array.prototype.concat

This patch makes Array.prototype.concat support subclassing Arrays
and constructing instances properly with Symbol.species. It is
guarded by the --harmony-species flag.

R=cbruni
LOG=Y
BUG=v8:4093

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

Cr-Commit-Position: refs/heads/master@{#33503}
parent 041e61f8
This diff is collapsed.
...@@ -16,6 +16,8 @@ assertEquals(MyArray, new MyArray().map(()=>{}).constructor); ...@@ -16,6 +16,8 @@ assertEquals(MyArray, new MyArray().map(()=>{}).constructor);
assertEquals(MyArray, new MyArray().filter(()=>{}).constructor); assertEquals(MyArray, new MyArray().filter(()=>{}).constructor);
assertEquals(MyArray, new MyArray().slice().constructor); assertEquals(MyArray, new MyArray().slice().constructor);
assertEquals(MyArray, new MyArray().splice().constructor); assertEquals(MyArray, new MyArray().splice().constructor);
assertEquals(MyArray, new MyArray().concat([1]).constructor);
assertEquals(1, new MyArray().concat([1])[0]);
// Subclasses can override @@species to return the another class // Subclasses can override @@species to return the another class
...@@ -27,6 +29,7 @@ assertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor); ...@@ -27,6 +29,7 @@ assertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor);
assertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor); assertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor);
assertEquals(MyArray, new MyOtherArray().slice().constructor); assertEquals(MyArray, new MyOtherArray().slice().constructor);
assertEquals(MyArray, new MyOtherArray().splice().constructor); assertEquals(MyArray, new MyOtherArray().splice().constructor);
assertEquals(MyArray, new MyOtherArray().concat().constructor);
// Array methods on non-arrays return arrays // Array methods on non-arrays return arrays
...@@ -44,11 +47,15 @@ assertEquals(MyObject, ...@@ -44,11 +47,15 @@ assertEquals(MyObject,
Array.prototype.slice.call(new MyNonArray()).constructor); Array.prototype.slice.call(new MyNonArray()).constructor);
assertEquals(MyObject, assertEquals(MyObject,
Array.prototype.splice.call(new MyNonArray()).constructor); Array.prototype.splice.call(new MyNonArray()).constructor);
assertEquals(MyObject,
Array.prototype.concat.call(new MyNonArray()).constructor);
assertEquals(undefined, assertEquals(undefined,
Array.prototype.map.call(new MyNonArray(), ()=>{}).length); Array.prototype.map.call(new MyNonArray(), ()=>{}).length);
assertEquals(undefined, assertEquals(undefined,
Array.prototype.filter.call(new MyNonArray(), ()=>{}).length); Array.prototype.filter.call(new MyNonArray(), ()=>{}).length);
assertEquals(undefined,
Array.prototype.concat.call(new MyNonArray(), ()=>{}).length);
// slice and splice actually do explicitly define the length for some reason // 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.slice.call(new MyNonArray()).length);
assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length); assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length);
...@@ -61,6 +68,9 @@ assertEquals(Array, ...@@ -61,6 +68,9 @@ assertEquals(Array,
Realm.eval(realm, "[]"), ()=>{}).constructor); Realm.eval(realm, "[]"), ()=>{}).constructor);
assertFalse(Array === Realm.eval(realm, "[]").map(()=>{}).constructor); assertFalse(Array === Realm.eval(realm, "[]").map(()=>{}).constructor);
assertFalse(Array === Realm.eval(realm, "[].map(()=>{}).constructor")); assertFalse(Array === Realm.eval(realm, "[].map(()=>{}).constructor"));
assertEquals(Array,
Array.prototype.concat.call(
Realm.eval(realm, "[]")).constructor);
// Defaults when constructor or @@species is missing or non-constructor // Defaults when constructor or @@species is missing or non-constructor
...@@ -74,6 +84,7 @@ assertEquals(MyOtherDefaultArray, ...@@ -74,6 +84,7 @@ assertEquals(MyOtherDefaultArray,
new MyOtherDefaultArray().map(()=>{}).constructor); new MyOtherDefaultArray().map(()=>{}).constructor);
MyOtherDefaultArray.prototype.constructor = undefined; MyOtherDefaultArray.prototype.constructor = undefined;
assertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor); assertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor);
assertEquals(Array, new MyOtherDefaultArray().concat().constructor);
// Exceptions propagated when getting constructor @@species throws // Exceptions propagated when getting constructor @@species throws
...@@ -100,6 +111,7 @@ assertThrows(() => new FrozenArray([1]).map(()=>0), TypeError); ...@@ -100,6 +111,7 @@ assertThrows(() => new FrozenArray([1]).map(()=>0), TypeError);
assertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError); assertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError);
assertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError); assertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError);
assertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError); assertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError);
assertThrows(() => new FrozenArray([]).concat([1]), TypeError);
// Verify call counts and constructor parameters // Verify call counts and constructor parameters
...@@ -130,6 +142,13 @@ assertEquals(MyObservedArray, ...@@ -130,6 +142,13 @@ assertEquals(MyObservedArray,
assertEquals(1, count); assertEquals(1, count);
assertArrayEquals([0], params); assertArrayEquals([0], params);
count = 0;
params = undefined;
assertEquals(MyObservedArray,
new MyObservedArray().concat().constructor);
assertEquals(1, count);
assertArrayEquals([0], params);
count = 0; count = 0;
params = undefined; params = undefined;
assertEquals(MyObservedArray, assertEquals(MyObservedArray,
......
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