diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Promise/race | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Promise/race')
94 files changed, 3704 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js new file mode 100644 index 0000000000..fadedf1e24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js @@ -0,0 +1,12 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race is callable +es6id: S25.4.4.3_A1.1_T1 +author: Sam Mikes +description: Promise.race is callable +---*/ +assert.sameValue(typeof Promise.race, "function", 'The value of `typeof Promise.race` is expected to be "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js new file mode 100644 index 0000000000..0200158ab5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js @@ -0,0 +1,15 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race returns a new promise +es6id: S25.4.4.3_A2.1_T1 +author: Sam Mikes +description: Promise.race returns a new promise +---*/ + +var p = Promise.race([]); + +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js new file mode 100644 index 0000000000..1adfb40d63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js @@ -0,0 +1,19 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race rejects on non-iterable argument +es6id: S25.4.4.3_A2.2_T1 +author: Sam Mikes +description: Promise.race rejects if argument is not object or is non-iterable +flags: [async] +---*/ + +var nonIterable = 3; + +Promise.race(nonIterable).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(nonIterable) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js new file mode 100644 index 0000000000..3555d007f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js @@ -0,0 +1,17 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race rejects on non-iterable argument +es6id: S25.4.4.3_A2.2_T2 +author: Sam Mikes +description: Promise.race rejects if argument is not object or is non-iterable +flags: [async] +---*/ + +Promise.race(new Error("abrupt")).then(function() { + throw new Test262Error('Promise unexpectedly resolved: Promise.race(abruptCompletion) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js new file mode 100644 index 0000000000..7e8f21d0da --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js @@ -0,0 +1,28 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race rejects when GetIterator() returns an abrupt completion + 4. Let iterator be GetIterator(iterable). + 5. IfAbruptRejectPromise(iterator, promiseCapability) +es6id: S25.4.4.3_A2.2_T3 +author: Sam Mikes +description: Promise.race rejects if GetIterator throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +Object.defineProperty(iterThrows, Symbol.iterator, { + get: function() { + throw new Error("abrupt completion"); + } +}); + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw'); +}, function(err) { + assert(!!(err instanceof Error), 'The value of !!(err instanceof Error) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js new file mode 100644 index 0000000000..8e01562462 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js @@ -0,0 +1,20 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race throws on invalid 'this' + Note: must have at least one element in array, or else Promise.race + never exercises the code that throws +es6id: S25.4.4.3_A3.1_T1 +author: Sam Mikes +description: Promise.race throws if 'this' does not conform to Promise constructor +---*/ + +function ZeroArgConstructor() {} + +assert.throws(TypeError, function() { + Promise.race.call(ZeroArgConstructor, [3]); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js new file mode 100644 index 0000000000..ac83127e8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js @@ -0,0 +1,22 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race must throw TypeError per + CreatePromiseCapabilityRecord step 8 when + promiseCapabliity.[[Resolve]] is not callable +es6id: S25.4.4.3_A3.1_T2 +author: Sam Mikes +description: Promise.race throws TypeError, even on empty array, when 'this' does not conform to Promise constructor +---*/ + +function BadPromiseConstructor(f) { + f(undefined, undefined); +} + +assert.throws(TypeError, function() { + Promise.race.call(BadPromiseConstructor, []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js new file mode 100644 index 0000000000..e4602242f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A4.1_T1 +author: Sam Mikes +description: Promise.race rejects if IteratorStep throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +var error = new Test262Error(); +iterThrows[Symbol.iterator] = function() { + return { + next: function() { + throw error; + } + }; +}; + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); +}, function(reason) { + assert.sameValue(reason, error, 'The value of reason is expected to equal the value of error'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js new file mode 100644 index 0000000000..c8aeb4602f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A4.1_T2 +author: Sam Mikes +description: Promise.race rejects if IteratorStep throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +Object.defineProperty(iterThrows, Symbol.iterator, { + get: function() { + return { + next: function() { + var v = {}; + Object.defineProperty(v, 'value', { + get: function() { + throw new Error("abrupt completion"); + } + }); + return v; + } + }; + } +}); + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js new file mode 100644 index 0000000000..e8dfc87992 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A5.1_T1 +author: Sam Mikes +description: Promise.race([]) never settles +flags: [async] +---*/ + +var p = Promise.race([]); + +p.then(function() { + throw new Test262Error("Never settles."); +}, function() { + throw new Test262Error("Never settles."); +}).then($DONE, $DONE); + +// use three 'then's to allow above to settle +// if this is a buggy Promise.race implementation +Promise.resolve().then().then().then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js new file mode 100644 index 0000000000..27dd872a3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A6.1_T1 +author: Sam Mikes +description: Promise.race([1]) settles immediately +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p = Promise.race([1]); + +sequence.push(1); + +p.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js new file mode 100644 index 0000000000..5be746bfab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A6.2_T1 +author: Sam Mikes +description: Promise.race([p1]) settles immediately +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.reject(1), + p = Promise.race([p1]); + +sequence.push(1); + +p.then(function() { + throw new Test262Error("Should not fulfill."); +}, function() { + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); +checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js new file mode 100644 index 0000000000..768f25c842 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.resolve(1), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js new file mode 100644 index 0000000000..72b7200f85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T2 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.resolve(1), + p2 = new Promise(function() {}), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js new file mode 100644 index 0000000000..ce763b023a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T3 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = new Promise(function() {}), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js new file mode 100644 index 0000000000..b38ba8eae6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.2_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.reject(1), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function() { + throw new Test262Error("Should not be fulfilled - expected rejection."); +}, function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js new file mode 100644 index 0000000000..303441a11d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.3_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +flags: [async] +---*/ + +var resolveP1, rejectP2, + p1 = new Promise(function(resolve) { + resolveP1 = resolve; + }), + p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; + }); + +rejectP2(new Error("Promise.race should not see this if P1 already resolved")); +resolveP1(1); + +Promise.race([p1, p2]).then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js new file mode 100644 index 0000000000..7081e0b3f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.3_T2 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +flags: [async] +---*/ + +var resolveP1, rejectP2, + p1 = new Promise(function(resolve) { + resolveP1 = resolve; + }), + p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; + }); + +Promise.race([p1, p2]).then(function() { + throw new Test262Error("Should not be fulfilled: expected rejection."); +}, function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); +}).then($DONE, $DONE); + +rejectP2(2); +resolveP1(1); diff --git a/js/src/tests/test262/built-ins/Promise/race/browser.js b/js/src/tests/test262/built-ins/Promise/race/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js new file mode 100644 index 0000000000..47dc31e96d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js @@ -0,0 +1,101 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3 +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.race ( iterable ) + + ... + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + ... + + 25.4.1.5.1 GetCapabilitiesExecutor Functions + ... + 3. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception. + 4. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception. + 5. Set promiseCapability.[[Resolve]] to resolve. + 6. Set promiseCapability.[[Reject]] to reject. + ... +---*/ + +var checkPoint = ""; +function fn1(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn1.resolve = function() { + throw new Test262Error(); +}; +Promise.race.call(fn1 , []); +assert.sameValue(checkPoint, "abc", "executor initially called with no arguments"); + +checkPoint = ""; +function fn2(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn2.resolve = function() { + throw new Test262Error(); +}; +Promise.race.call(fn2 , []); +assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)"); + +checkPoint = ""; +function fn3(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn3, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn3 , []); +}, "executor initially called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)"); + +checkPoint = ""; +function fn4(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn4, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn4 , []); +}, "executor initially called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)"); + +checkPoint = ""; +function fn5(executor) { + checkPoint += "a"; + executor("invalid value", 123); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn5, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn5 , []); +}, "executor initially called with (String, Number)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js new file mode 100644 index 0000000000..d5e5bc4783 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js @@ -0,0 +1,85 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3 +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.race ( iterable ) + + ... + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + ... + + 25.4.1.5 NewPromiseCapability ( C ) + ... + 4. Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1). + 5. Set the [[Capability]] internal slot of executor to promiseCapability. + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). + 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception. + 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception. + ... +---*/ + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + }, []); +}, "executor not called at all"); +assert.sameValue(checkPoint, "a", "executor not called at all"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; + }, []); +}, "executor called with no arguments"); +assert.sameValue(checkPoint, "ab", "executor called with no arguments"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; + }, []); +}, "executor called with (undefined, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; + }, []); +}, "executor called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; + }, []); +}, "executor called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(123, "invalid value"); + checkPoint += "b"; + }, []); +}, "executor called with (Number, String)"); +assert.sameValue(checkPoint, "ab", "executor called with (Number, String)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js new file mode 100644 index 0000000000..81988b5dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a constructor value that throws an error +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.race.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js new file mode 100644 index 0000000000..105b3fba4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js @@ -0,0 +1,39 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a constructor value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 10. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + 13. Return Completion(result). +features: [class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.race.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js new file mode 100644 index 0000000000..5b6b4d7af4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a non-constructor value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +---*/ + +assert.throws(TypeError, function() { + Promise.race.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js new file mode 100644 index 0000000000..c2dd20aa00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a non-object value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.race.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js new file mode 100644 index 0000000000..a152a8b46c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js @@ -0,0 +1,51 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error from `Promise.resolve` +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +features: [Symbol.iterator] +---*/ + +var iterDoneSpy = {}; +var returnCount = 0; +iterDoneSpy[Symbol.iterator] = function() { + return { + next: function() { + return { + value: null, + done: false + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.resolve = function() { + throw err; +}; + +Promise.race(iterDoneSpy); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..00a17b0568 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error from `Promise.resolve` +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +flags: [async] +---*/ + +var err = new Test262Error(); +var CustomPromise = function(executor) { + return new Promise(executor); +}; + +CustomPromise.resolve = function() { + throw err; +}; + +Promise.race.call(CustomPromise, [1]) + .then(function() { + throw new Test262Error('The promise should be rejected.'); + }, function(reason) { + assert.sameValue(reason, err); + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..d5cb474730 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (promise rejection) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +flags: [async] +---*/ + +var error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get: function() { + throw error; + } +}); + +Promise.race([new Promise(function() {})]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js new file mode 100644 index 0000000000..8c0b8224f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.race ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.race(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..38a700ed21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.race +info: | + Runtime Semantics: PerformPromiseRace + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var p1 = Promise.resolve(1); +var p2 = Promise.resolve(1); +var p3 = Promise.reject(1); +var p4 = Promise.resolve(1); +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.race([p1, p2, p3, p4]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 4, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..43e6718a67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.race +info: | + Runtime Semantics: PerformPromiseRace + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.race([]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 0, '`resolve` not called for empty iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..a84e88a5fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..1f5857c182 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1, 1, 1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..137367bef1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js new file mode 100644 index 0000000000..87f3f16312 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + [...] +---*/ + +var originalCallCount = 0; +var newCallCount = 0; +var P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +var originalThenable = { + then: function() { + originalCallCount += 1; + } +}; +var newThenable = { + then: function() { + newCallCount += 1; + } +}; + +Promise.race.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js new file mode 100644 index 0000000000..8ffdf6efae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js @@ -0,0 +1,53 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +es6id: 25.4.4.3 +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var resolve = Promise.resolve; +var callCount = 0; +var current = p1; +var next = p2; +var afterNext = p3; + +Promise.resolve = function(nextValue) { + assert.sameValue( + nextValue, current, '`resolve` invoked with next iterated value' + ); + assert.sameValue( + arguments.length, 1, '`resolve` invoked with a single argument' + ); + assert.sameValue(this, Promise, '`this` value set to the constructor'); + + current = next; + next = afterNext; + afterNext = null; + + callCount += 1; + + return resolve.apply(Promise, arguments); +}; + +Promise.race([p1, p2, p3]); + +assert.sameValue( + callCount, 3, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js new file mode 100644 index 0000000000..b6d7e9f67c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js @@ -0,0 +1,52 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var iter = {}; +var returnCount = 0; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; +promise.then = function() { + throw new Test262Error(); +}; + +Promise.race(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js new file mode 100644 index 0000000000..2b391dd34e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +promise.then = function() { + throw error; +}; + +Promise.race([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js new file mode 100644 index 0000000000..e67faa28cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (closing iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var iter = {}; +var returnCount = 0; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; +Object.defineProperty(promise, 'then', { + get: function() { + throw new Test262Error(); + } +}); + +Promise.race(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..2c97adee85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +Object.defineProperty(promise, 'then', { + get: function() { + throw error; + } +}); + +Promise.race([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then.js new file mode 100644 index 0000000000..3f1ecab814 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then.js @@ -0,0 +1,57 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +es6id: 25.4.4.3 +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var callCount = 0; +var currentThis = p1; +var nextThis = p2; +var afterNextThis = p3; + +p1.then = p2.then = p3.then = function(a, b) { + assert.sameValue(typeof a, 'function', 'type of first argument'); + assert.sameValue( + a.length, + 1, + 'ES6 25.4.1.3.2: The length property of a promise resolve function is 1.' + ); + assert.sameValue(typeof b, 'function', 'type of second argument'); + assert.sameValue( + b.length, + 1, + 'ES6 25.4.1.3.1: The length property of a promise reject function is 1.' + ); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + assert.sameValue(this, currentThis, '`this` value'); + + currentThis = nextThis; + nextThis = afterNextThis; + afterNextThis = null; + + callCount += 1; +}; + +Promise.race([p1, p2, p3]); + +assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..666fbeead7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `false` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..c34066d33c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `null` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..9c077ee83a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..acf600e838 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolve when argument is a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race("a").then(function(v) { + assert.sameValue(v, "a"); + }, function() { + $DONE('The promise should be resolved, but was rejected'); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..86dee03495 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..1f85fed248 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `true` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..b14a91acf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `undefined` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js new file mode 100644 index 0000000000..b7342a76b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js new file mode 100644 index 0000000000..742970a8a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js new file mode 100644 index 0000000000..4c471a6d55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js new file mode 100644 index 0000000000..f35bb7abf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: "" + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..e5bb702110 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js new file mode 100644 index 0000000000..d633aba403 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..dbefa628a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..74adaa02ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +---*/ + +var iterNextValThrows = {}; +var returnCount = 0; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + }, + return: function() { + returnCount += 1; + } + }; +}; + +Promise.race(iterNextValThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js new file mode 100644 index 0000000000..866d9af062 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when accessing an iterator result's `value` property (rejecting + promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + } + }; +}; + +Promise.race(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js new file mode 100644 index 0000000000..06d9baa284 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return false; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js new file mode 100644 index 0000000000..4e450e961d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return null; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js new file mode 100644 index 0000000000..2c5db3d16d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return 1; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js new file mode 100644 index 0000000000..10e860ba82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return ""; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..d1493510ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return Symbol(); + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js new file mode 100644 index 0000000000..0be813db4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return true; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..1a8e034a33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return undefined; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js new file mode 100644 index 0000000000..624fc107e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error when advancing the provided iterable (not closing iterator) +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var returnCount = 0; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + throw new Test262Error('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + }, + return: function() { + returnCount += 1; + } + }; +}; + +Promise.race(iterStepThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js new file mode 100644 index 0000000000..3b3a3e35a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when advancing the provided iterable (rejecting promise) +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + throw new Test262Error('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + } + }; +}; + +Promise.race(iterStepThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/length.js b/js/src/tests/test262/built-ins/Promise/race/length.js new file mode 100644 index 0000000000..0fa1f53d8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.3 +description: Promise.race `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.race.length, 1); + +verifyNotEnumerable(Promise.race, 'length'); +verifyNotWritable(Promise.race, 'length'); +verifyConfigurable(Promise.race, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/name.js b/js/src/tests/test262/built-ins/Promise/race/name.js new file mode 100644 index 0000000000..e88d3384ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.3 +description: Promise.race `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.race.name, 'race'); + +verifyNotEnumerable(Promise.race, 'name'); +verifyNotWritable(Promise.race, 'name'); +verifyConfigurable(Promise.race, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js new file mode 100644 index 0000000000..a6e0f33d59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.race does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.race), false, 'isConstructor(Promise.race) must return false'); + +assert.throws(TypeError, () => { + new Promise.race([]); +}, '`new Promise.race([])` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/prop-desc.js b/js/src/tests/test262/built-ins/Promise/race/prop-desc.js new file mode 100644 index 0000000000..ff99905270 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright 2015 Jordan Harband. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: 25.4.4.3_A1.2_T1 +author: Jordan Harband +description: Promise.race property descriptor +info: | + ES6 Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'race'); +verifyWritable(Promise, 'race'); +verifyConfigurable(Promise, 'race'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js new file mode 100644 index 0000000000..4ff5cea941 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(); + }); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function() { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js new file mode 100644 index 0000000000..25601b9361 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js @@ -0,0 +1,65 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiserace +description: > + Promise.race does not prevent resolve from being called multiple times. +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +includes: [promiseHelper.js] +---*/ + +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function reject(value) { + callCount += 1; + sequence.push(value); + } + executor(() => { + throw new Test262Error(); + }, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let pReject; + +let a = { + then(_, rejecter) { + pReject = rejecter; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to race()'); + +Promise.race.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to race()'); + +pReject(1); +pReject(2); +pReject(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js new file mode 100644 index 0000000000..9c19236a74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(); + }); + } +}; +var rejector = { + then: function(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(); + }); + } +}; + +Promise.race([fulfiller, rejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js new file mode 100644 index 0000000000..32404d046b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + resolve(); + } +}; +var rejector = { + then: function(_, reject) { + reject(); + } +}; + +Promise.race([fulfiller, rejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-immed.js b/js/src/tests/test262/built-ins/Promise/race/reject-immed.js new file mode 100644 index 0000000000..9e079b496e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-immed.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through immediate invocation of the provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + reject(); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function() { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js new file mode 100644 index 0000000000..df4a3c4daf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js @@ -0,0 +1,62 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiserace +description: > + Promise.race does not prevent resolve from being called multiple times. +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +includes: [promiseHelper.js] +---*/ + +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function resolve(value) { + callCount += 1; + sequence.push(value); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +let pResolve; +let a = { + then(resolver, rejector) { + pResolve = resolver; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to race()'); + +Promise.race.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to race()'); + +pResolve(1); +pResolve(2); +pResolve(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..6640930c46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +features: [arrow-function] +includes: [promiseHelper.js] +---*/ + +let sequence = [1]; +let lateRejector = { + then(resolve, reject) { + return new Promise((resolve) => { + sequence.push(3); + resolve(); + sequence.push(4); + }).then(() => { + sequence.push(5); + resolve(9); + sequence.push(6); + reject(); + sequence.push(7); + }); + } +}; +sequence.push(2); + +Promise.race([lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 9); + assert.sameValue(sequence.length, 7); + checkSequence(sequence); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..c981b0e04e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +features: [arrow-function] +---*/ + +let resolver = { + then(resolve) { + resolve(42); + } +}; +let lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.race([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js new file mode 100644 index 0000000000..b47413a78c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.race ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.race(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js new file mode 100644 index 0000000000..1cee83de79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var thenable = { + then: function(resolve) { + resolve(23); + } +}; + +Promise.race([thenable]) + .then(function(value) { + if (value !== 23) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js new file mode 100644 index 0000000000..4fd8820f2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var value = {}; +var thenable = { + then: function(resolve) { + resolve(value); + } +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js new file mode 100644 index 0000000000..d31b42eacc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var thenable = { + then: function(resolve) { + resolve(poisonedThen); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the correct value.'); + return; + } + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js new file mode 100644 index 0000000000..a31f9b2133 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js @@ -0,0 +1,56 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenableValue = { + then: function(resolve) { + resolve(value); + } +}; +var thenable = new Promise(function(resolve) { + resolve(); +}); + +thenable.then = function(resolve) { + resolve(thenableValue); +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-self.js b/js/src/tests/test262/built-ins/Promise/race/resolve-self.js new file mode 100644 index 0000000000..13da6da562 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-self.js @@ -0,0 +1,59 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var self, resolve; +var builtinResolve = Promise.resolve; +var thenable = { + then: function(r) { + resolve = r; + } +}; + +try { + Promise.resolve = function(v) { + return v; + }; + self = Promise.race([thenable]); +} finally { + Promise.resolve = builtinResolve; +} + +resolve(self); + +self.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(value) { + if (!value) { + $DONE('The promise should be rejected with a value.'); + return; + } + if (value.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js new file mode 100644 index 0000000000..72a91dc07f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenableValue = { + then: function(resolve) { + resolve(value); + } +}; +var thenable = { + then: function(resolve) { + resolve(thenableValue); + } +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..6336fa8900 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [promiseHelper.js] +---*/ + +let a = new Promise(resolve => resolve({})); +let sequence = [1]; +Promise.all([ + Promise.race([a]).then(resolved => { + sequence.push(4); + }), + a.then(() => { + sequence.push(3); + }).then(() => { + sequence.push(5); + }), +]).then(() => { + assert.sameValue(sequence.length, 5); + checkSequence(sequence); +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js new file mode 100644 index 0000000000..0c96494897 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [promiseHelper.js] +---*/ + +let a = Promise.reject(''); +let b = new Promise(resolve => resolve('')); +let c = new Promise((_, reject) => reject('')); +let sequence = [1]; +Promise.all([ + a.catch(() => { + sequence.push(3); + }), + Promise.race([a, b, c]).then(() => { + // This should not be present when the final + // sequence is evaluated. + sequence.push(5); + }), + b.then(() => { + sequence.push(4); + }), +]).catch(() => { + assert.sameValue(sequence.length, 4); + checkSequence(sequence); +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..882684d04f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [compareArray.js,promiseHelper.js] +---*/ + +let a = new Promise((_, reject) => reject('a')); +let b = new Promise((_, reject) => reject('b')); +let sequence = [1]; +Promise.all([ + a.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + return checkSequence(sequence, 'Expected to be called first.'); + }), + Promise.race([a, b]).catch(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + return checkSequence(sequence, 'Expected to be called third.'); + }), + b.catch(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + return checkSequence(sequence, 'Expected to be called second.'); + }) +]).then(result => { + assert.compareArray(result, [true, true, true]); + assert.sameValue(sequence.length, 5); + checkSequence(sequence); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js new file mode 100644 index 0000000000..316db984bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [compareArray.js,promiseHelper.js] +---*/ + +let a = new Promise(resolve => resolve('a')); +let b = new Promise(resolve => resolve('b')); +let sequence = [1]; +Promise.all([ + a.then(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + return checkSequence(sequence, 'Expected to be called first.'); + }), + Promise.race([a, b]).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + return checkSequence(sequence, 'Expected to be called third.'); + }), + b.then(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + return checkSequence(sequence, 'Expected to be called second.'); + }) +]).then(result => { + assert.compareArray(result, [true, true, true]); + assert.sameValue(sequence.length, 5); + checkSequence(sequence) +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js b/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js new file mode 100644 index 0000000000..5423f9a653 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolution the first resolved promise +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +---*/ + +let a = Promise.reject('a').catch((v) => v); +let b = Promise.resolve('b').then((v) => { throw v }); +let c = Promise.reject('c').then((v) => { throw v; }); +let d = Promise.resolve('d').finally((v) => v); +let e = Promise.reject('e').finally((v) => v); +let f = Promise.resolve('f').finally((v) => { throw v; }); +let g = Promise.reject('g').finally((v) => { throw v; }); +let h = Promise.reject('h').then((v) => v, () => 'j'); +let i = Promise.resolve('i').then(v => v); + +Promise.race([a, b, c, d, e, f, g, h, i]).then(winner => { + assert.sameValue(winner, 'a'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js b/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js new file mode 100644 index 0000000000..a19c469ffc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3.1 +description: > + Each Promise.race element is called with the same reject function. +info: | + Runtime Semantics: PerformPromiseRace ( iteratorRecord, promiseCapability, C ) + + ... + j. Let result be Invoke(nextPromise, "then", «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + ... +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(Test262Error.thrower, rejectFunction); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; + +var p1 = { + then: function(onFulfilled, onRejected) { + callCount1 += 1; + assert.sameValue(onRejected, rejectFunction, "p1.then"); + } +}; +var p2 = { + then: function(onFulfilled, onRejected) { + callCount2 += 1; + assert.sameValue(onRejected, rejectFunction, "p2.then"); + } +}; + +Promise.race.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, "p1.then call count"); +assert.sameValue(callCount2, 1, "p2.then call count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js b/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js new file mode 100644 index 0000000000..92c3cb5466 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3.1 +description: > + Each Promise.race element is called with the same resolve function. +info: | + Runtime Semantics: PerformPromiseRace ( iteratorRecord, promiseCapability, C ) + + ... + j. Let result be Invoke(nextPromise, "then", «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + ... +---*/ + +function resolveFunction() {} + +function Constructor(executor) { + executor(resolveFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; + +var p1 = { + then: function(onFulfilled, onRejected) { + callCount1 += 1; + assert.sameValue(onFulfilled, resolveFunction, "p1.then"); + } +}; +var p2 = { + then: function(onFulfilled, onRejected) { + callCount2 += 1; + assert.sameValue(onFulfilled, resolveFunction, "p2.then"); + } +}; + +Promise.race.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, "p1.then call count"); +assert.sameValue(callCount2, 1, "p2.then call count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/shell.js b/js/src/tests/test262/built-ins/Promise/race/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/race/species-get-error.js b/js/src/tests/test262/built-ins/Promise/race/species-get-error.js new file mode 100644 index 0000000000..1198715f8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/species-get-error.js @@ -0,0 +1,30 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.race() does not retrieve `Symbol.species` property of the `this` value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... +features: [Symbol.species] +---*/ + +function C(executor) { + executor(function() {}, function() {}); +} +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error("Getter for Symbol.species called"); + } +}); +C.resolve = function() { + throw new Test262Error(); +}; + +Promise.race.call(C, []); + +reportCompare(0, 0); |