| C = class extends Promise { } |
| N = class { } |
| N[Symbol.species] = function() { throw "this should never be called"; } |
| |
| function id(x) { return x; } |
| |
| testFunctions = [ |
| [Promise.prototype.then, [id]] |
| ]; |
| |
| objProp = Object.defineProperty; |
| |
| function funcThrows(func, args) { |
| try { |
| func.call(...args) |
| return false; |
| } catch (e) { |
| return true; |
| } |
| } |
| |
| function makeC() { |
| return new C(function(resolve) { resolve(1); }); |
| } |
| |
| function test(testData) { |
| "use strict"; |
| let [protoFunction, args] = testData; |
| let foo = makeC() |
| let n = new N(); |
| |
| // Test promise defaults cases. |
| foo = makeC(); |
| |
| objProp(C, Symbol.species, { value: undefined, writable: true}); |
| let bar = protoFunction.call(foo, ...args); |
| if (!(bar instanceof Promise) || bar instanceof C) |
| throw Error(); |
| |
| C[Symbol.species] = null; |
| bar = protoFunction.call(foo, ...args); |
| if (!(bar instanceof Promise) || bar instanceof C) |
| throw Error(); |
| |
| // Test species is custom constructor. |
| let called = false; |
| function species() { |
| called = true; |
| return new C(...arguments); |
| } |
| |
| C[Symbol.species] = species; |
| bar = protoFunction.call(foo, ...args); |
| |
| if (!(bar instanceof Promise) || !(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); |