summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Bargull <andre.bargull@gmail.com>2015-12-02 18:06:40 +0100
committerAndré Bargull <andre.bargull@gmail.com>2015-12-02 18:06:40 +0100
commit5279bcb1742601e8ecc63caeab751a63998b8f5c (patch)
treecc2649cb313209f09ce5f82a93ca9cc23e9354dd
parentfd44cd73dfbce0b515a2474b7cd505d6176a9eb5 (diff)
downloadqtdeclarative-testsuites-5279bcb1742601e8ecc63caeab751a63998b8f5c.tar.gz
Improve test coverage for various Promise methods
-rwxr-xr-xtest/built-ins/Promise/all/call-resolve-element-after-return.js51
-rwxr-xr-xtest/built-ins/Promise/all/call-resolve-element-items.js48
-rwxr-xr-xtest/built-ins/Promise/all/call-resolve-element.js41
-rwxr-xr-xtest/built-ins/Promise/all/capability-executor-called-twice.js79
-rwxr-xr-xtest/built-ins/Promise/all/capability-executor-not-callable.js83
-rwxr-xr-xtest/built-ins/Promise/all/does-not-invoke-array-setters.js35
-rwxr-xr-xtest/built-ins/Promise/all/new-resolve-function.js46
-rwxr-xr-xtest/built-ins/Promise/all/resolve-before-loop-exit-from-same.js71
-rwxr-xr-xtest/built-ins/Promise/all/resolve-before-loop-exit.js67
-rwxr-xr-xtest/built-ins/Promise/all/resolve-from-same-thenable.js77
-rwxr-xr-xtest/built-ins/Promise/all/same-reject-function.js41
-rwxr-xr-xtest/built-ins/Promise/exception-after-resolve-in-executor.js31
-rwxr-xr-xtest/built-ins/Promise/exception-after-resolve-in-thenable-job.js36
-rwxr-xr-xtest/built-ins/Promise/prototype/then/capability-executor-called-twice.js96
-rwxr-xr-xtest/built-ins/Promise/prototype/then/capability-executor-not-callable.js101
-rwxr-xr-xtest/built-ins/Promise/prototype/then/context-check-on-entry.js24
-rwxr-xr-xtest/built-ins/Promise/prototype/then/deferred-is-resolved-value.js65
-rwxr-xr-xtest/built-ins/Promise/race/capability-executor-called-twice.js79
-rwxr-xr-xtest/built-ins/Promise/race/capability-executor-not-callable.js83
-rwxr-xr-xtest/built-ins/Promise/race/same-reject-function.js41
-rwxr-xr-xtest/built-ins/Promise/race/same-resolve-function.js41
-rwxr-xr-xtest/built-ins/Promise/reject/capability-executor-called-twice.js79
-rwxr-xr-xtest/built-ins/Promise/reject/capability-executor-not-callable.js83
-rwxr-xr-xtest/built-ins/Promise/resolve/capability-executor-called-twice.js79
-rwxr-xr-xtest/built-ins/Promise/resolve/capability-executor-not-callable.js83
-rwxr-xr-xtest/built-ins/Promise/resolve/context-non-object-with-promise.js48
-rwxr-xr-xtest/built-ins/Promise/resolve/resolve-from-promise-capability.js31
27 files changed, 1639 insertions, 0 deletions
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 000000000..f313998e4
--- /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 000000000..2a6f9328c
--- /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 000000000..fedc06418
--- /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 000000000..357991eb3
--- /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 000000000..d09cef6a9
--- /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 000000000..baac7abeb
--- /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 000000000..b8edf247d
--- /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 000000000..0ad1df9ea
--- /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 000000000..397931fed
--- /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 000000000..328c5997e
--- /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 000000000..c862d9563
--- /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 000000000..747c56279
--- /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 000000000..f10db969b
--- /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 000000000..63368d6a1
--- /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 000000000..be23e05d3
--- /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 000000000..80981c751
--- /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 000000000..442de0de5
--- /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 000000000..70b2e8e1d
--- /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 000000000..b0710691f
--- /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 000000000..79f5a4221
--- /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 000000000..6c9d9b26c
--- /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 000000000..012fc134d
--- /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 000000000..cc62ea380
--- /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 000000000..2ff388c47
--- /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 000000000..e70155f83
--- /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 000000000..c41a83229
--- /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 000000000..1a8ddd487
--- /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()");