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