From 6e9d88a293ec123c0a3856ed8d1a597a3ffd7cd9 Mon Sep 17 00:00:00 2001
From: Mike Pennisi <mike@mikepennisi.com>
Date: Wed, 6 Jan 2016 10:26:46 -0500
Subject: [PATCH] Extend coverage for PerformPromiseRace

---
 .../Promise/race/invoke-resolve-return.js     | 47 ++++++++++++++++
 test/built-ins/Promise/race/iter-close.js     | 54 +++++++++++++++++++
 test/built-ins/Promise/race/iter-step-err.js  | 50 +++++++++++++++++
 3 files changed, 151 insertions(+)
 create mode 100644 test/built-ins/Promise/race/invoke-resolve-return.js
 create mode 100644 test/built-ins/Promise/race/iter-close.js
 create mode 100644 test/built-ins/Promise/race/iter-step-err.js

diff --git a/test/built-ins/Promise/race/invoke-resolve-return.js b/test/built-ins/Promise/race/invoke-resolve-return.js
new file mode 100644
index 0000000000..970ce94337
--- /dev/null
+++ b/test/built-ins/Promise/race/invoke-resolve-return.js
@@ -0,0 +1,47 @@
+// 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');
diff --git a/test/built-ins/Promise/race/iter-close.js b/test/built-ins/Promise/race/iter-close.js
new file mode 100644
index 0000000000..02858893aa
--- /dev/null
+++ b/test/built-ins/Promise/race/iter-close.js
@@ -0,0 +1,54 @@
+// 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
+es6id: 25.4.4.3
+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 err = new Test262Error();
+var iterDoneSpy = {};
+var callCount = 0;
+var CustomPromise = function(executor) {
+  return new Promise(executor);
+};
+iterDoneSpy[Symbol.iterator] = function() {
+  return {
+    next: function() {
+      return { value: null, done: false };
+    },
+    return: function() {
+      callCount += 1;
+    }
+  };
+};
+
+CustomPromise.resolve = function() {
+  throw err;
+};
+
+Promise.race.call(CustomPromise, iterDoneSpy)
+  .then(function() {
+    $ERROR('The promise should be rejected.');
+  }, function(reason) {
+    assert.sameValue(reason, err);
+    $DONE();
+  });
+
+assert.sameValue(callCount, 1);
diff --git a/test/built-ins/Promise/race/iter-step-err.js b/test/built-ins/Promise/race/iter-step-err.js
new file mode 100644
index 0000000000..e248475500
--- /dev/null
+++ b/test/built-ins/Promise/race/iter-step-err.js
@@ -0,0 +1,50 @@
+// 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
+es6id: 25.4.4.3
+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 error = new Test262Error();
+Object.defineProperty(poisonedDone, 'done', {
+  get: function() {
+    throw error;
+  }
+});
+Object.defineProperty(poisonedDone, 'value', {
+  get: function() {
+    $ERROR('The `value` property should not be accessed.');
+  }
+});
+
+iterStepThrows[Symbol.iterator] = function() {
+  return {
+    next: function() {
+      return poisonedDone;
+    }
+  };
+};
+
+Promise.race(iterStepThrows).then(function() {
+  $ERROR('The promise should be rejected.');
+}, function(reason) {
+  assert.sameValue(reason, error);
+}).then($DONE, $DONE);
-- 
GitLab