blob: dca7c89ecedfeaa7517349442a7d8a3fe7ee269e [file] [log] [blame]
C = class extends Array { }
N = class { }
N[Symbol.species] = function() { throw "this should never be called"; }
function id(x) { return x; }
testFunctions = [
[Array.prototype.concat, []],
[Array.prototype.slice, [1,2]],
[Array.prototype.splice, []],
[Array.prototype.splice, [0,1]],
[Array.prototype.map, [id]],
[Array.prototype.filter, [id]]
];
objProp = Object.defineProperty;
function funcThrows(func, args) {
try {
func.call(...args)
return false;
} catch (e) {
return true;
}
}
function test(testData) {
"use strict";
let [protoFunction, args] = testData;
let foo = new C(10);
let n = new N();
// Test non-array ignores constructor.
objProp(n, "constructor", { value: C });
let bar = protoFunction.call(n, ...args);
if (!(bar instanceof Array) || bar instanceof N || bar instanceof C)
throw Error();
objProp(foo, "constructor", { value: null });
if (!funcThrows(protoFunction, [foo, ...args]))
throw "didn't throw";
// Test array defaults cases.
foo = new C(10);
objProp(C, Symbol.species, { value: undefined, writable: true});
bar = protoFunction.call(foo, ...args);
if (!(bar instanceof Array) || bar instanceof C)
throw Error();
C[Symbol.species] = null;
bar = protoFunction.call(foo, ...args);
if (!(bar instanceof Array) || bar instanceof C)
throw Error();
// Test species is custom constructor.
let called = false;
function species(...args) {
called = true;
return new C(...args);
}
C[Symbol.species] = species;
bar = protoFunction.call(foo, ...args);
if (!(bar instanceof Array) || !(bar instanceof C) || !called)
throw Error("failed on " + protoFunction);
function speciesThrows() {
throw Error();
}
C[Symbol.species] = speciesThrows;
if (!funcThrows(protoFunction, [foo, ...args]))
throw "didn't throw";
C[Symbol.species] = true;
if (!funcThrows(protoFunction, [foo, ...args]))
throw "didn't throw";
}
testFunctions.forEach(test);