From 5279bcb1742601e8ecc63caeab751a63998b8f5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Bargull?= <andre.bargull@gmail.com>
Date: Wed, 2 Dec 2015 18:06:40 +0100
Subject: [PATCH] Improve test coverage for various Promise methods

---
 .../all/call-resolve-element-after-return.js  |  51 +++++++++
 .../Promise/all/call-resolve-element-items.js |  48 +++++++++
 .../Promise/all/call-resolve-element.js       |  41 +++++++
 .../all/capability-executor-called-twice.js   |  79 ++++++++++++++
 .../all/capability-executor-not-callable.js   |  83 ++++++++++++++
 .../all/does-not-invoke-array-setters.js      |  35 ++++++
 .../Promise/all/new-resolve-function.js       |  46 ++++++++
 .../all/resolve-before-loop-exit-from-same.js |  71 ++++++++++++
 .../Promise/all/resolve-before-loop-exit.js   |  67 ++++++++++++
 .../Promise/all/resolve-from-same-thenable.js |  77 +++++++++++++
 .../Promise/all/same-reject-function.js       |  41 +++++++
 .../exception-after-resolve-in-executor.js    |  31 ++++++
 ...exception-after-resolve-in-thenable-job.js |  36 +++++++
 .../then/capability-executor-called-twice.js  |  96 +++++++++++++++++
 .../then/capability-executor-not-callable.js  | 101 ++++++++++++++++++
 .../prototype/then/context-check-on-entry.js  |  24 +++++
 .../then/deferred-is-resolved-value.js        |  65 +++++++++++
 .../race/capability-executor-called-twice.js  |  79 ++++++++++++++
 .../race/capability-executor-not-callable.js  |  83 ++++++++++++++
 .../Promise/race/same-reject-function.js      |  41 +++++++
 .../Promise/race/same-resolve-function.js     |  41 +++++++
 .../capability-executor-called-twice.js       |  79 ++++++++++++++
 .../capability-executor-not-callable.js       |  83 ++++++++++++++
 .../capability-executor-called-twice.js       |  79 ++++++++++++++
 .../capability-executor-not-callable.js       |  83 ++++++++++++++
 .../context-non-object-with-promise.js        |  48 +++++++++
 .../resolve-from-promise-capability.js        |  31 ++++++
 27 files changed, 1639 insertions(+)
 create mode 100755 test/built-ins/Promise/all/call-resolve-element-after-return.js
 create mode 100755 test/built-ins/Promise/all/call-resolve-element-items.js
 create mode 100755 test/built-ins/Promise/all/call-resolve-element.js
 create mode 100755 test/built-ins/Promise/all/capability-executor-called-twice.js
 create mode 100755 test/built-ins/Promise/all/capability-executor-not-callable.js
 create mode 100755 test/built-ins/Promise/all/does-not-invoke-array-setters.js
 create mode 100755 test/built-ins/Promise/all/new-resolve-function.js
 create mode 100755 test/built-ins/Promise/all/resolve-before-loop-exit-from-same.js
 create mode 100755 test/built-ins/Promise/all/resolve-before-loop-exit.js
 create mode 100755 test/built-ins/Promise/all/resolve-from-same-thenable.js
 create mode 100755 test/built-ins/Promise/all/same-reject-function.js
 create mode 100755 test/built-ins/Promise/exception-after-resolve-in-executor.js
 create mode 100755 test/built-ins/Promise/exception-after-resolve-in-thenable-job.js
 create mode 100755 test/built-ins/Promise/prototype/then/capability-executor-called-twice.js
 create mode 100755 test/built-ins/Promise/prototype/then/capability-executor-not-callable.js
 create mode 100755 test/built-ins/Promise/prototype/then/context-check-on-entry.js
 create mode 100755 test/built-ins/Promise/prototype/then/deferred-is-resolved-value.js
 create mode 100755 test/built-ins/Promise/race/capability-executor-called-twice.js
 create mode 100755 test/built-ins/Promise/race/capability-executor-not-callable.js
 create mode 100755 test/built-ins/Promise/race/same-reject-function.js
 create mode 100755 test/built-ins/Promise/race/same-resolve-function.js
 create mode 100755 test/built-ins/Promise/reject/capability-executor-called-twice.js
 create mode 100755 test/built-ins/Promise/reject/capability-executor-not-callable.js
 create mode 100755 test/built-ins/Promise/resolve/capability-executor-called-twice.js
 create mode 100755 test/built-ins/Promise/resolve/capability-executor-not-callable.js
 create mode 100755 test/built-ins/Promise/resolve/context-non-object-with-promise.js
 create mode 100755 test/built-ins/Promise/resolve/resolve-from-promise-capability.js

diff --git a/test/built-ins/Promise/all/call-resolve-element-after-return.js b/test/built-ins/Promise/all/call-resolve-element-after-return.js
new file mode 100755
index 0000000000..f313998e42
--- /dev/null
+++ b/test/built-ins/Promise/all/call-resolve-element-after-return.js
@@ -0,0 +1,51 @@
+// 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.1.2
+description: >
+  Cannot change result value of resolved Promise.all element after Promise.all() returned.
+info: >
+  Promise.all Resolve Element Functions
+
+  1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+  2. If alreadyCalled.[[value]] is true, return undefined.
+  3. Set alreadyCalled.[[value]] to true.
+  ...
+---*/
+
+var callCount = 0;
+var valuesArray;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    valuesArray = values;
+    assert(Array.isArray(values), "values is array");
+    assert.sameValue(values.length, 1, "values.length");
+    assert.sameValue(values[0], "expectedValue", "values[0]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1OnFulfilled;
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    p1OnFulfilled = onFulfilled;
+    onFulfilled("expectedValue");
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1]);
+
+assert.sameValue(callCount, 1, "callCount after call to all()");
+assert.sameValue(valuesArray[0], "expectedValue", "valuesArray after call to all()");
+
+p1OnFulfilled("unexpectedValue");
+
+assert.sameValue(callCount, 1, "callCount after call to onFulfilled()");
+assert.sameValue(valuesArray[0], "expectedValue", "valuesArray after call to onFulfilled()");
diff --git a/test/built-ins/Promise/all/call-resolve-element-items.js b/test/built-ins/Promise/all/call-resolve-element-items.js
new file mode 100755
index 0000000000..2a6f9328c6
--- /dev/null
+++ b/test/built-ins/Promise/all/call-resolve-element-items.js
@@ -0,0 +1,48 @@
+// 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.1.2
+description: >
+  Cannot change result value of resolved Promise.all elements.
+info: >
+  Promise.all Resolve Element Functions
+
+  1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+  2. If alreadyCalled.[[value]] is true, return undefined.
+  3. Set alreadyCalled.[[value]] to true.
+  ...
+---*/
+
+var callCount = 0;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    assert(Array.isArray(values), "values is array");
+    assert.sameValue(values.length, 2, "values length");
+    assert.sameValue(values[0], "expectedValue-p1", "values[0]");
+    assert.sameValue(values[1], "expectedValue-p2", "values[1]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("expectedValue-p1");
+    onFulfilled("unexpectedValue-p1");
+  }
+};
+var p2 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("expectedValue-p2");
+    onFulfilled("unexpectedValue-p2");
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1, p2]);
+
+assert.sameValue(callCount, 1, "callCount after call to all()");
diff --git a/test/built-ins/Promise/all/call-resolve-element.js b/test/built-ins/Promise/all/call-resolve-element.js
new file mode 100755
index 0000000000..fedc064180
--- /dev/null
+++ b/test/built-ins/Promise/all/call-resolve-element.js
@@ -0,0 +1,41 @@
+// 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.1.2
+description: >
+  Cannot change result value of resolved Promise.all element.
+info: >
+  Promise.all Resolve Element Functions
+
+  1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+  2. If alreadyCalled.[[value]] is true, return undefined.
+  3. Set alreadyCalled.[[value]] to true.
+  ...
+---*/
+
+var callCount = 0;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    assert(Array.isArray(values), "values is array");
+    assert.sameValue(values.length, 1, "values length");
+    assert.sameValue(values[0], "expectedValue", "values[0]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("expectedValue");
+    onFulfilled("unexpectedValue");
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1]);
+
+assert.sameValue(callCount, 1, "callCount after call to all()");
diff --git a/test/built-ins/Promise/all/capability-executor-called-twice.js b/test/built-ins/Promise/all/capability-executor-called-twice.js
new file mode 100755
index 0000000000..357991eb39
--- /dev/null
+++ b/test/built-ins/Promise/all/capability-executor-called-twice.js
@@ -0,0 +1,79 @@
+// 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.1
+description: >
+  Throws a TypeError if capabilities executor already called with non-undefined values.
+info: >
+  Promise.all ( 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 = "";
+Promise.all.call(function(executor) {
+  checkPoint += "a";
+  executor();
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, []);
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+Promise.all.call(function(executor) {
+  checkPoint += "a";
+  executor(undefined, undefined);
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, []);
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.all.call(function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.all.call(function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.all.call(function(executor) {
+    checkPoint += "a";
+    executor("invalid value", 123);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
diff --git a/test/built-ins/Promise/all/capability-executor-not-callable.js b/test/built-ins/Promise/all/capability-executor-not-callable.js
new file mode 100755
index 0000000000..d09cef6a9d
--- /dev/null
+++ b/test/built-ins/Promise/all/capability-executor-not-callable.js
@@ -0,0 +1,83 @@
+// 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.1
+description: >
+  Throws a TypeError if either resolve or reject capability is not callable.
+info: >
+  Promise.all ( 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.all.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.all.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.all.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.all.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.all.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.all.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)");
diff --git a/test/built-ins/Promise/all/does-not-invoke-array-setters.js b/test/built-ins/Promise/all/does-not-invoke-array-setters.js
new file mode 100755
index 0000000000..baac7abebe
--- /dev/null
+++ b/test/built-ins/Promise/all/does-not-invoke-array-setters.js
@@ -0,0 +1,35 @@
+// 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.1.1
+description: >
+  Indexed setter properties on Array.prototype are not invoked.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  4. Let remainingElementsCount be a new Record { [[value]]: 1 }.
+  ...
+  6.d ...
+    ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
+    iii. If remainingElementsCount.[[value]] is 0,
+      1. Let valuesArray be CreateArrayFromList(values).
+      ...
+  ...
+
+  7.3.16 CreateArrayFromList (elements)
+    ...
+    4. For each element e of elements
+      a. Let status be CreateDataProperty(array, ToString(n), e).
+      b. Assert: status is true.
+    ...
+---*/
+
+Object.defineProperty(Array.prototype, 0, {
+  set: function() {
+    $ERROR("Setter on Array.prototype called");
+  }
+});
+
+Promise.all([42]).then(function(){ $DONE(); }, $DONE);
diff --git a/test/built-ins/Promise/all/new-resolve-function.js b/test/built-ins/Promise/all/new-resolve-function.js
new file mode 100755
index 0000000000..b8edf247dd
--- /dev/null
+++ b/test/built-ins/Promise/all/new-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.1.1
+description: >
+  Each Promise.all element is called with a new Promise.all Resolve Element function.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  k. Let resolveElement be a new built-in function object as defined in Promise.all Resolve Element Functions.
+  ...
+  r. Let result be Invoke(nextPromise, "then", «resolveElement, resultCapability.[[Reject]]»).
+  ...
+---*/
+
+function resolveFunction() { }
+
+function Constructor(executor) {
+  executor(resolveFunction, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var callCount1 = 0, callCount2 = 0;
+var p1OnFulfilled;
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    callCount1 += 1;
+    p1OnFulfilled = onFulfilled;
+    assert.notSameValue(onFulfilled, resolveFunction, "p1.then");
+  }
+};
+var p2 = {
+  then: function(onFulfilled, onRejected) {
+    callCount2 += 1;
+    assert.notSameValue(onFulfilled, resolveFunction, "p2.then");
+    assert.notSameValue(onFulfilled, p1OnFulfilled, "p1.onFulfilled != p2.onFulfilled");
+  }
+};
+
+Promise.all.call(Constructor, [p1, p2]);
+
+assert.sameValue(callCount1, 1, "p1.then call count");
+assert.sameValue(callCount2, 1, "p2.then call count");
diff --git a/test/built-ins/Promise/all/resolve-before-loop-exit-from-same.js b/test/built-ins/Promise/all/resolve-before-loop-exit-from-same.js
new file mode 100755
index 0000000000..0ad1df9ea9
--- /dev/null
+++ b/test/built-ins/Promise/all/resolve-before-loop-exit-from-same.js
@@ -0,0 +1,71 @@
+// 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.1.1
+description: >
+  Cannot tamper remainingElementsCount when Promise.all resolve element function is called twice in a row.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  4. Let remainingElementsCount be a new Record { [[value]]: 1 }.
+  ...
+  6.d ...
+    ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
+    iii. If remainingElementsCount.[[value]] is 0,
+      1. Let valuesArray be CreateArrayFromList(values).
+      2. Let resolveResult be Call(resultCapability.[[Resolve]], undefined, «valuesArray»).
+      3. ReturnIfAbrupt(resolveResult).
+  ...
+
+  25.4.4.1.2 Promise.all Resolve Element Functions
+    1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+    2. If alreadyCalled.[[value]] is true, return undefined.
+    3. Set alreadyCalled.[[value]] to true.
+    ...
+---*/
+
+var callCount = 0;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    assert(Array.isArray(values), "values is array");
+    assert.sameValue(values.length, 3, "values length");
+    assert.sameValue(values[0], "p1-fulfill", "values[0]");
+    assert.sameValue(values[1], "p2-fulfill", "values[1]");
+    assert.sameValue(values[2], "p3-fulfill", "values[2]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1OnFulfilled;
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    p1OnFulfilled = onFulfilled;
+  }
+};
+var p2 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("p2-fulfill");
+    onFulfilled("p2-fulfill-unexpected");
+  }
+};
+var p3 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("p3-fulfill");
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1, p2, p3]);
+
+assert.sameValue(callCount, 0, "callCount after call to all()");
+
+p1OnFulfilled("p1-fulfill");
+
+assert.sameValue(callCount, 1, "callCount after resolving p1");
diff --git a/test/built-ins/Promise/all/resolve-before-loop-exit.js b/test/built-ins/Promise/all/resolve-before-loop-exit.js
new file mode 100755
index 0000000000..397931fed8
--- /dev/null
+++ b/test/built-ins/Promise/all/resolve-before-loop-exit.js
@@ -0,0 +1,67 @@
+// 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.1.1
+description: >
+  Cannot tamper remainingElementsCount when two Promise.all resolve element functions are called in succession.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  4. Let remainingElementsCount be a new Record { [[value]]: 1 }.
+  ...
+  6.d ...
+    ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
+    iii. If remainingElementsCount.[[value]] is 0,
+      1. Let valuesArray be CreateArrayFromList(values).
+      2. Let resolveResult be Call(resultCapability.[[Resolve]], undefined, «valuesArray»).
+      3. ReturnIfAbrupt(resolveResult).
+  ...
+
+  25.4.4.1.2 Promise.all Resolve Element Functions
+    1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+    2. If alreadyCalled.[[value]] is true, return undefined.
+    3. Set alreadyCalled.[[value]] to true.
+    ...
+---*/
+
+var callCount = 0;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    assert(Array.isArray(values), "values is array");
+    assert.sameValue(values.length, 3, "values length");
+    assert.sameValue(values[0], "p1-fulfill", "values[0]");
+    assert.sameValue(values[1], "p2-fulfill", "values[1]");
+    assert.sameValue(values[2], "p3-fulfill", "values[2]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1OnFulfilled;
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    p1OnFulfilled = onFulfilled;
+  }
+};
+var p2 = {
+  then: function(onFulfilled, onRejected) {
+    p1OnFulfilled("p1-fulfill");
+    onFulfilled("p2-fulfill");
+  }
+};
+var p3 = {
+  then: function(onFulfilled, onRejected) {
+    onFulfilled("p3-fulfill");
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1, p2, p3]);
+
+assert.sameValue(callCount, 1, "callCount after call to all()");
diff --git a/test/built-ins/Promise/all/resolve-from-same-thenable.js b/test/built-ins/Promise/all/resolve-from-same-thenable.js
new file mode 100755
index 0000000000..328c5997ee
--- /dev/null
+++ b/test/built-ins/Promise/all/resolve-from-same-thenable.js
@@ -0,0 +1,77 @@
+// 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.1.1
+description: >
+  Cannot tamper remainingElementsCount when Promise.all resolve element function is called multiple times.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  4. Let remainingElementsCount be a new Record { [[value]]: 1 }.
+  ...
+  6.d ...
+    ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
+    iii. If remainingElementsCount.[[value]] is 0,
+      1. Let valuesArray be CreateArrayFromList(values).
+      2. Let resolveResult be Call(resultCapability.[[Resolve]], undefined, «valuesArray»).
+      3. ReturnIfAbrupt(resolveResult).
+  ...
+
+  25.4.4.1.2 Promise.all Resolve Element Functions
+    1. Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
+    2. If alreadyCalled.[[value]] is true, return undefined.
+    3. Set alreadyCalled.[[value]] to true.
+    ...
+---*/
+
+var callCount = 0;
+
+function Constructor(executor) {
+  function resolve(values) {
+    callCount += 1;
+    assert(Array.isArray(values, "values is array"));
+    assert.sameValue(values.length, 3, "values length");
+    assert.sameValue(values[0], "p1-fulfill", "values[0]");
+    assert.sameValue(values[1], "p2-fulfill", "values[1]");
+    assert.sameValue(values[2], "p3-fulfill", "values[2]");
+  }
+  executor(resolve, $ERROR);
+}
+Constructor.resolve = function(v) { return v; };
+
+var p1OnFulfilled, p2OnFulfilled, p3OnFulfilled;
+
+var p1 = {
+  then: function(onFulfilled, onRejected) {
+    p1OnFulfilled = onFulfilled;
+  }
+};
+var p2 = {
+  then: function(onFulfilled, onRejected) {
+    p2OnFulfilled = onFulfilled;
+  }
+};
+var p3 = {
+  then: function(onFulfilled, onRejected) {
+    p3OnFulfilled = onFulfilled;
+  }
+};
+
+assert.sameValue(callCount, 0, "callCount before call to all()");
+
+Promise.all.call(Constructor, [p1, p2, p3]);
+
+assert.sameValue(callCount, 0, "callCount after call to all()");
+
+p1OnFulfilled("p1-fulfill");
+p1OnFulfilled("p1-fulfill-unexpected-1");
+p1OnFulfilled("p1-fulfill-unexpected-2");
+
+assert.sameValue(callCount, 0, "callCount after resolving p1");
+
+p2OnFulfilled("p2-fulfill");
+p3OnFulfilled("p3-fulfill");
+
+assert.sameValue(callCount, 1, "callCount after resolving all elements");
diff --git a/test/built-ins/Promise/all/same-reject-function.js b/test/built-ins/Promise/all/same-reject-function.js
new file mode 100755
index 0000000000..c862d9563e
--- /dev/null
+++ b/test/built-ins/Promise/all/same-reject-function.js
@@ -0,0 +1,41 @@
+// 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.1.1
+description: >
+  Each Promise.all element is called with the same reject function.
+info: >
+  Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability)
+
+  ...
+  r. Let result be Invoke(nextPromise, "then", «resolveElement, resultCapability.[[Reject]]»).
+  ...
+---*/
+
+function rejectFunction() { }
+
+function Constructor(executor) {
+  executor($ERROR, 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.all.call(Constructor, [p1, p2]);
+
+assert.sameValue(callCount1, 1, "p1.then call count");
+assert.sameValue(callCount2, 1, "p2.then call count");
diff --git a/test/built-ins/Promise/exception-after-resolve-in-executor.js b/test/built-ins/Promise/exception-after-resolve-in-executor.js
new file mode 100755
index 0000000000..747c562797
--- /dev/null
+++ b/test/built-ins/Promise/exception-after-resolve-in-executor.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.3.1
+description: >
+  Already resolved promise is not rejected when executor throws an exception.
+info: >
+  Promise ( executor )
+
+  ...
+  8. Let resolvingFunctions be CreateResolvingFunctions(promise).
+  9. Let completion be Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
+  10. If completion is an abrupt completion, then
+    a. Let status be Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»).
+    b. ReturnIfAbrupt(status).
+  ...
+---*/
+
+var thenable = {
+  then: function(resolve) {
+    resolve();
+  }
+};
+
+function executor(resolve, reject) {
+  resolve(thenable);
+  throw new Error("ignored exception");
+}
+
+new Promise(executor).then($DONE, $DONE);
diff --git a/test/built-ins/Promise/exception-after-resolve-in-thenable-job.js b/test/built-ins/Promise/exception-after-resolve-in-thenable-job.js
new file mode 100755
index 0000000000..f10db969b1
--- /dev/null
+++ b/test/built-ins/Promise/exception-after-resolve-in-thenable-job.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.2.2
+description: >
+  Already resolved promise is not rejected when then() function throws an exception.
+info: >
+  PromiseResolveThenableJob ( promiseToResolve, thenable, then )
+
+  1. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve).
+  2. Let thenCallResult be Call(then, thenable, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
+  3. If thenCallResult is an abrupt completion,
+    a. Let status be Call(resolvingFunctions.[[Reject]], undefined, «thenCallResult.[[value]]»)
+    b. NextJob Completion(status).
+  ...
+---*/
+
+var thenable = {
+  then: function(resolve) {
+    resolve();
+  }
+};
+
+var thenableWithError = {
+  then: function(resolve) {
+    resolve(thenable);
+    throw new Error("ignored exception");
+  }
+};
+
+function executor(resolve, reject) {
+  resolve(thenableWithError);
+}
+
+new Promise(executor).then($DONE, $DONE);
diff --git a/test/built-ins/Promise/prototype/then/capability-executor-called-twice.js b/test/built-ins/Promise/prototype/then/capability-executor-called-twice.js
new file mode 100755
index 0000000000..63368d6a13
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/capability-executor-called-twice.js
@@ -0,0 +1,96 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+  Throws a TypeError if capabilities executor already called with non-undefined values.
+info: >
+  Promise.prototype.then ( onFulfilled , onRejected )
+
+  ...
+  5. Let promiseCapability be NewPromiseCapability(C).
+  6. 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 constructorFunction;
+
+var promise = new class extends Promise {
+  constructor(executor) {
+    if (constructorFunction) {
+      constructorFunction(executor);
+      return {};
+    }
+    return super(executor);
+  }
+}(function(){});
+
+var checkPoint = "";
+constructorFunction = function(executor) {
+  checkPoint += "a";
+  executor();
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+};
+promise.then();
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+constructorFunction = function(executor) {
+  checkPoint += "a";
+  executor(undefined, undefined);
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+};
+promise.then();
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  };
+  promise.then();
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  };
+  promise.then();
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor("invalid value", 123);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  };
+  promise.then();
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
diff --git a/test/built-ins/Promise/prototype/then/capability-executor-not-callable.js b/test/built-ins/Promise/prototype/then/capability-executor-not-callable.js
new file mode 100755
index 0000000000..be23e05d3c
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/capability-executor-not-callable.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.5.3
+description: >
+  Throws a TypeError if either resolve or reject capability is not callable.
+info: >
+  Promise.prototype.then ( onFulfilled , onRejected )
+
+  ...
+  5. Let promiseCapability be NewPromiseCapability(C).
+  6. 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 constructorFunction;
+
+var promise = new class extends Promise {
+  constructor(executor) {
+    if (constructorFunction) {
+      constructorFunction(executor);
+      return {};
+    }
+    return super(executor);
+  }
+}(function(){});
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+  };
+  promise.then();
+}, "executor not called at all");
+assert.sameValue(checkPoint, "a", "executor not called at all");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor();
+    checkPoint += "b";
+  };
+  promise.then();
+}, "executor called with no arguments");
+assert.sameValue(checkPoint, "ab", "executor called with no arguments");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(undefined, undefined);
+    checkPoint += "b";
+  };
+  promise.then();
+}, "executor called with (undefined, undefined)");
+assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+  };
+  promise.then();
+}, "executor called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+  };
+  promise.then();
+}, "executor called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  constructorFunction = function(executor) {
+    checkPoint += "a";
+    executor(123, "invalid value");
+    checkPoint += "b";
+  };
+  promise.then();
+}, "executor called with (Number, String)");
+assert.sameValue(checkPoint, "ab", "executor called with (Number, String)");
diff --git a/test/built-ins/Promise/prototype/then/context-check-on-entry.js b/test/built-ins/Promise/prototype/then/context-check-on-entry.js
new file mode 100755
index 0000000000..80981c7519
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/context-check-on-entry.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+  Throws a TypeError if `this` is not a Promise object.
+info: >
+  Promise.prototype.then ( onFulfilled , onRejected )
+
+  1. Let promise be the this value.
+  2. If IsPromise(promise) is false, throw a TypeError exception.
+  ...
+---*/
+
+var object = {
+  get constructor() {
+    $ERROR("get constructor called");
+  }
+};
+
+assert.throws(TypeError, function() {
+  Promise.prototype.then.call(object);
+});
diff --git a/test/built-ins/Promise/prototype/then/deferred-is-resolved-value.js b/test/built-ins/Promise/prototype/then/deferred-is-resolved-value.js
new file mode 100755
index 0000000000..442de0de5c
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/deferred-is-resolved-value.js
@@ -0,0 +1,65 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+  Promise reaction jobs do not check for cyclic resolutions.
+info: >
+  Promise.prototype.then ( onFulfilled , onRejected )
+
+  ...
+  5. Let resultCapability be NewPromiseCapability(C).
+  6. ReturnIfAbrupt(resultCapability).
+  7. Return PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability).
+
+  25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability )
+    ...
+    3. If IsCallable(onFulfilled) is false, then
+      a. Let onFulfilled be "Identity".
+    4. If IsCallable(onRejected) is false, then
+      a. Let onRejected be "Thrower".
+    5. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onFulfilled }.
+    6. Let rejectReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onRejected}.
+    ...
+    8. Else if the value of promise's [[PromiseState]] internal slot is "fulfilled",
+      a. Let value be the value of promise's [[PromiseResult]] internal slot.
+      b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, value»).
+    ...
+
+  25.4.2.1 PromiseReactionJob ( reaction, argument )
+    ...
+    4. If handler is "Identity", let handlerResult be NormalCompletion(argument).
+    ...
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined, «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var createBadPromise = false;
+var object = {};
+
+class P extends Promise {
+  constructor(executor) {
+    if (createBadPromise) {
+      executor(
+        function(v) {
+          assert.sameValue(v, object);
+          $DONE();
+        },
+        function(e) {
+          $DONE(e);
+        }
+      );
+      return object;
+    }
+    return super(executor);
+  }
+}
+
+var p = P.resolve(object);
+
+createBadPromise = true;
+var q = p.then();
+createBadPromise = false;
+
+assert.sameValue(q, object, "then() returns object");
diff --git a/test/built-ins/Promise/race/capability-executor-called-twice.js b/test/built-ins/Promise/race/capability-executor-called-twice.js
new file mode 100755
index 0000000000..70b2e8e1d6
--- /dev/null
+++ b/test/built-ins/Promise/race/capability-executor-called-twice.js
@@ -0,0 +1,79 @@
+// 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 = "";
+Promise.race.call(function(executor) {
+  checkPoint += "a";
+  executor();
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, []);
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+Promise.race.call(function(executor) {
+  checkPoint += "a";
+  executor(undefined, undefined);
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, []);
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.race.call(function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.race.call(function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.race.call(function(executor) {
+    checkPoint += "a";
+    executor("invalid value", 123);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, []);
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
diff --git a/test/built-ins/Promise/race/capability-executor-not-callable.js b/test/built-ins/Promise/race/capability-executor-not-callable.js
new file mode 100755
index 0000000000..b0710691f0
--- /dev/null
+++ b/test/built-ins/Promise/race/capability-executor-not-callable.js
@@ -0,0 +1,83 @@
+// 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)");
diff --git a/test/built-ins/Promise/race/same-reject-function.js b/test/built-ins/Promise/race/same-reject-function.js
new file mode 100755
index 0000000000..79f5a42217
--- /dev/null
+++ b/test/built-ins/Promise/race/same-reject-function.js
@@ -0,0 +1,41 @@
+// 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($ERROR, 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");
diff --git a/test/built-ins/Promise/race/same-resolve-function.js b/test/built-ins/Promise/race/same-resolve-function.js
new file mode 100755
index 0000000000..6c9d9b26c9
--- /dev/null
+++ b/test/built-ins/Promise/race/same-resolve-function.js
@@ -0,0 +1,41 @@
+// 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, $ERROR);
+}
+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");
diff --git a/test/built-ins/Promise/reject/capability-executor-called-twice.js b/test/built-ins/Promise/reject/capability-executor-called-twice.js
new file mode 100755
index 0000000000..012fc134d7
--- /dev/null
+++ b/test/built-ins/Promise/reject/capability-executor-called-twice.js
@@ -0,0 +1,79 @@
+// 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.4
+description: >
+  Throws a TypeError if capabilities executor already called with non-undefined values.
+info: >
+  Promise.reject ( r )
+
+  ...
+  3. Let promiseCapability be NewPromiseCapability(C).
+  4. 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 = "";
+Promise.reject.call(function(executor) {
+  checkPoint += "a";
+  executor();
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, {});
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+Promise.reject.call(function(executor) {
+  checkPoint += "a";
+  executor(undefined, undefined);
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, {});
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.reject.call(function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.reject.call(function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.reject.call(function(executor) {
+    checkPoint += "a";
+    executor("invalid value", 123);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
diff --git a/test/built-ins/Promise/reject/capability-executor-not-callable.js b/test/built-ins/Promise/reject/capability-executor-not-callable.js
new file mode 100755
index 0000000000..cc62ea380a
--- /dev/null
+++ b/test/built-ins/Promise/reject/capability-executor-not-callable.js
@@ -0,0 +1,83 @@
+// 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.4
+description: >
+  Throws a TypeError if either resolve or reject capability is not callable.
+info: >
+  Promise.reject ( r )
+
+  ...
+  3. Let promiseCapability be NewPromiseCapability(C).
+  4. 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.reject.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.reject.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.reject.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.reject.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.reject.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.reject.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)");
diff --git a/test/built-ins/Promise/resolve/capability-executor-called-twice.js b/test/built-ins/Promise/resolve/capability-executor-called-twice.js
new file mode 100755
index 0000000000..2ff388c47a
--- /dev/null
+++ b/test/built-ins/Promise/resolve/capability-executor-called-twice.js
@@ -0,0 +1,79 @@
+// 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.5
+description: >
+  Throws a TypeError if capabilities executor already called with non-undefined values.
+info: >
+  Promise.resolve ( x )
+
+  ...
+  4. Let promiseCapability be NewPromiseCapability(C).
+  5. 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 = "";
+Promise.resolve.call(function(executor) {
+  checkPoint += "a";
+  executor();
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, {});
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+Promise.resolve.call(function(executor) {
+  checkPoint += "a";
+  executor(undefined, undefined);
+  checkPoint += "b";
+  executor(function(){}, function(){});
+  checkPoint += "c";
+}, {});
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.resolve.call(function(executor) {
+    checkPoint += "a";
+    executor(undefined, function(){});
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.resolve.call(function(executor) {
+    checkPoint += "a";
+    executor(function(){}, undefined);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+  Promise.resolve.call(function(executor) {
+    checkPoint += "a";
+    executor("invalid value", 123);
+    checkPoint += "b";
+    executor(function(){}, function(){});
+    checkPoint += "c";
+  }, {});
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
diff --git a/test/built-ins/Promise/resolve/capability-executor-not-callable.js b/test/built-ins/Promise/resolve/capability-executor-not-callable.js
new file mode 100755
index 0000000000..e70155f831
--- /dev/null
+++ b/test/built-ins/Promise/resolve/capability-executor-not-callable.js
@@ -0,0 +1,83 @@
+// 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.5
+description: >
+  Throws a TypeError if either resolve or reject capability is not callable.
+info: >
+  Promise.resolve ( x )
+
+  ...
+  4. Let promiseCapability be NewPromiseCapability(C).
+  5. 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.resolve.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.resolve.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.resolve.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.resolve.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.resolve.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.resolve.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)");
diff --git a/test/built-ins/Promise/resolve/context-non-object-with-promise.js b/test/built-ins/Promise/resolve/context-non-object-with-promise.js
new file mode 100755
index 0000000000..c41a83229f
--- /dev/null
+++ b/test/built-ins/Promise/resolve/context-non-object-with-promise.js
@@ -0,0 +1,48 @@
+// 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.5
+description: >
+  Throws a TypeError if `this` is not an Object.
+info: >
+  Promise.resolve ( x )
+
+  1. Let C be the this value.
+  2. If Type(C) is not Object, throw a TypeError exception.
+  ...
+features: [Symbol]
+---*/
+
+var promise = new Promise(function(){}, function(){});
+
+promise.constructor = undefined;
+assert.throws(TypeError, function() {
+  Promise.resolve.call(undefined, promise);
+}, "`this` value is undefined");
+
+promise.constructor = null;
+assert.throws(TypeError, function() {
+  Promise.resolve.call(null, promise);
+}, "`this` value is null");
+
+promise.constructor = true;
+assert.throws(TypeError, function() {
+  Promise.resolve.call(true, promise);
+}, "`this` value is a Boolean");
+
+promise.constructor = 1;
+assert.throws(TypeError, function() {
+  Promise.resolve.call(1, promise);
+}, "`this` value is a Number");
+
+promise.constructor = "";
+assert.throws(TypeError, function() {
+  Promise.resolve.call("", promise);
+}, "`this` value is a String");
+
+var symbol = Symbol();
+promise.constructor = symbol;
+assert.throws(TypeError, function() {
+  Promise.resolve.call(symbol, promise);
+}, "`this` value is a Symbol");
diff --git a/test/built-ins/Promise/resolve/resolve-from-promise-capability.js b/test/built-ins/Promise/resolve/resolve-from-promise-capability.js
new file mode 100755
index 0000000000..1a8ddd487a
--- /dev/null
+++ b/test/built-ins/Promise/resolve/resolve-from-promise-capability.js
@@ -0,0 +1,31 @@
+// 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.5
+description: >
+  Resolve function is called after Promise constructor returns.
+info: >
+  Promise.resolve ( x )
+
+  ...
+  4. Let promiseCapability be NewPromiseCapability(C).
+  5. ReturnIfAbrupt(promiseCapability).
+  6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, «x»).
+  7. ReturnIfAbrupt(resolveResult).
+  ...
+---*/
+
+var callCount = 0;
+var object = {};
+
+Promise.resolve.call(function(executor) {
+  function resolve(v) {
+    callCount += 1;
+    assert.sameValue(v, object);
+  }
+  executor(resolve, $ERROR);
+  assert.sameValue(callCount, 0, "callCount before returning from constructor");
+}, object);
+
+assert.sameValue(callCount, 1, "callCount after call to resolve()");
-- 
GitLab