summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Promise/race
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Promise/race
parentInitial commit. (diff)
downloadfirefox-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')
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js12
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js15
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js19
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js17
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js20
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js27
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js41
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js25
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js27
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js101
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js85
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js41
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js41
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js47
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js43
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js44
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js49
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js52
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js40
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/invoke-then.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js34
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js55
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js52
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/length.js27
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/name.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js31
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/prop-desc.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/reject-deferred.js42
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js65
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js47
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/reject-immed.js37
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js62
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js47
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js37
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js42
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js47
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js49
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js56
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-self.js59
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js43
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js49
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js52
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js40
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/same-reject-function.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/race/species-get-error.js30
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, &laquo; nextValue &raquo;).
+---*/
+
+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, &laquo; nextValue &raquo;).
+---*/
+
+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);