diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Promise')
645 files changed, 25556 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/browser.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/length.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/length.js new file mode 100644 index 0000000000..a2556d0a44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/length.js @@ -0,0 +1,34 @@ +// 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.6 +description: > + get Promise [ @@species ].length is 0. +info: | + get Promise [ @@species ] + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Symbol.species] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Promise, Symbol.species); + +assert.sameValue(desc.get.length, 0); + +verifyNotEnumerable(desc.get, "length"); +verifyNotWritable(desc.get, "length"); +verifyConfigurable(desc.get, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/prop-desc.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/prop-desc.js new file mode 100644 index 0000000000..13904b6a3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.6 +description: Promise `Symbol.species` property +info: | + Promise[@@species] is an accessor property whose set accessor function is + undefined. + + ES6 Section 17: + + Every accessor property described in clauses 18 through 26 and in Annex B.2 + has the attributes {[[Enumerable]]: false, [[Configurable]]: true } unless + otherwise specified. +features: [Symbol.species] +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Promise, Symbol.species); + +assert.sameValue(desc.set, undefined); +assert.sameValue(typeof desc.get, 'function'); + +verifyNotEnumerable(Promise, Symbol.species); +verifyConfigurable(Promise, Symbol.species); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/return-value.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/return-value.js new file mode 100644 index 0000000000..f4298bc6ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/return-value.js @@ -0,0 +1,16 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.6 +description: Promise `Symbol.species` accessor function return value +info: | + 1. Return the this value. +features: [Symbol.species] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Promise, Symbol.species); +var thisValue = {}; + +assert.sameValue(desc.get.call(thisValue), thisValue); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/shell.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species-name.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species-name.js new file mode 100644 index 0000000000..30f74b923b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species-name.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.6 +description: > + Promise[Symbol.species] accessor property get name +info: | + 25.4.4.6 get Promise [ @@species ] + + ... + The value of the name property of this function is "get [Symbol.species]". +features: [Symbol.species] +---*/ + +var descriptor = Object.getOwnPropertyDescriptor(Promise, Symbol.species); + +assert.sameValue( + descriptor.get.name, + 'get [Symbol.species]' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js new file mode 100644 index 0000000000..24da4e82ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js @@ -0,0 +1,20 @@ +// Copyright 2015 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise has a property at `Symbol.species` +es6id: 6.1.5.1 +author: Sam Mikes +description: Promise[Symbol.species] exists per spec +includes: [propertyHelper.js] +features: [Symbol.species] +---*/ + +assert.sameValue(Promise[Symbol.species], Promise, "Promise[Symbol.species] is Promise"); + +verifyNotWritable(Promise, Symbol.species, Symbol.species); +verifyNotEnumerable(Promise, Symbol.species); +verifyConfigurable(Promise, Symbol.species); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js new file mode 100644 index 0000000000..1cf29b6a21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js @@ -0,0 +1,12 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all is callable +es6id: 25.4.4.1_A1.1_T1 +author: Sam Mikes +description: Promise.all is callable +---*/ +assert.sameValue(typeof Promise.all, "function", 'The value of `typeof Promise.all` is expected to be "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js new file mode 100644 index 0000000000..5d27aaab35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js @@ -0,0 +1,14 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all([]) is a Promise +es6id: 25.4.4.1_A2.1_T1 +author: Sam Mikes +description: Promise.all returns a Promise +---*/ + +var p = Promise.all([]); +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.2_T1.js new file mode 100644 index 0000000000..8a3eaceae9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.2_T1.js @@ -0,0 +1,28 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all([]) is resolved immediately +es6id: 25.4.4.1_A2.2_T1 +author: Sam Mikes +includes: [promiseHelper.js] +description: Promise.all([]) returns immediately +flags: [async] +---*/ + +var sequence = []; + +Promise.all([]).then(function() { + sequence.push(2); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); +}).then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "Promises resolved in unexpected sequence"); +}).then($DONE, $DONE); + +sequence.push(1); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js new file mode 100644 index 0000000000..c737bb4f99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js @@ -0,0 +1,17 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all([]) returns a promise for a new empty array +es6id: 25.4.4.1_A2.3_T1 +author: Sam Mikes +description: Promise.all([]) returns a promise for an array +flags: [async] +---*/ + +var arg = []; + +Promise.all(arg).then(function(result) { + assert(!!(result instanceof Array), 'The value of !!(result instanceof Array) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js new file mode 100644 index 0000000000..ad9bfa6c48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js @@ -0,0 +1,17 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all is resolved with a new empty array +es6id: 25.4.4.1_A2.3_T2 +author: Sam Mikes +description: Promise.all([]) returns a Promise for an empty array +flags: [async] +---*/ + +var arg = []; + +Promise.all(arg).then(function(result) { + assert.sameValue(result.length, 0, 'The value of result.length is expected to be 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js new file mode 100644 index 0000000000..09b598f3fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js @@ -0,0 +1,17 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.all([]) is resolved with Promise for a new empty array +es6id: 25.4.4.1_A2.3_T3 +author: Sam Mikes +description: Promise.all([]) is resolved with a Promise for a new array +flags: [async] +---*/ + +var arg = []; + +Promise.all(arg).then(function(result) { + assert.notSameValue(result, arg, 'The value of result is expected to not equal the value of `arg`'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js new file mode 100644 index 0000000000..88e7558c3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all expects an iterable argument; + ref 7.4.1 non-Object fails CheckIterable + ref 7.4.2 GetIterator throws TypeError if CheckIterable fails +es6id: 25.4.4.1_A3.1_T1 +author: Sam Mikes +description: Promise.all(3) returns Promise rejected with TypeError +flags: [async] +---*/ + +var nonIterable = 3; + +Promise.all(nonIterable).then(function() { + throw new Test262Error('Promise unexpectedly resolved: Promise.all(nonIterable) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js new file mode 100644 index 0000000000..23c5d8390d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js @@ -0,0 +1,21 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all expects an iterable argument; + fails if recieves an abrupt completion + ref 7.4.1 non-Object fails CheckIterable + ref 7.4.2 GetIterator throws TypeError if CheckIterable fails +es6id: S25.4.4.1_A3.1_T2 +author: Sam Mikes +description: Promise.all(new Error()) returns Promise rejected with TypeError +flags: [async] +---*/ + +Promise.all(new Error("abrupt")).then(function() { + throw new Test262Error('Promise unexpectedly resolved: Promise.all(abruptCompletion) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js new file mode 100644 index 0000000000..9a93d8bd9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all expects an iterable argument; + fails if GetIterator returns an abrupt completion. +es6id: S25.4.4.1_A3.1_T3 +author: Sam Mikes +description: Promise.all((throw on GetIterator)) returns Promise rejected with TypeError +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +Object.defineProperty(iterThrows, Symbol.iterator, { + get: function() { + throw new Error("abrupt completion"); + } +}); + +Promise.all(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.all(iterThrows) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof Error), 'The value of !!(err instanceof Error) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A4.1_T1.js new file mode 100644 index 0000000000..e63ccb33c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A4.1_T1.js @@ -0,0 +1,18 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all should throw if 'this' does not conform to Promise constructor +es6id: S25.4.4.1_A4.1_T1 +description: this must conform to Promise constructor in Promise.all +author: Sam Mikes +---*/ + +function ZeroArgConstructor() {} + +assert.throws(TypeError, function() { + Promise.all.call(ZeroArgConstructor, []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js new file mode 100644 index 0000000000..b670d9e937 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js @@ -0,0 +1,30 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all expects an iterable argument; + rejects if IteratorStep() throws +es6id: S25.4.4.1_A5.1_T1 +author: Sam Mikes +description: iterator.next throws, causing Promise.all to reject +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +var error = new Test262Error(); +iterThrows[Symbol.iterator] = function() { + return { + next: function() { + throw error; + } + }; +}; + +Promise.all(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly resolved: Promise.all(iterThrows) should throw TypeError'); +}, function(reason) { + assert.sameValue(reason, error, 'The value of reason is expected to equal the value of error'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js new file mode 100644 index 0000000000..0cc08b3f2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js @@ -0,0 +1,24 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all with 1-element array + should accept an array with settled promise +es6id: S25.4.4.1_A6.1_T2 +author: Sam Mikes +description: Promise.all([p1]) is resolved with a promise for a one-element array +flags: [async] +---*/ + +var p1 = Promise.resolve(3); + +var pAll = Promise.all([p1]); + +pAll.then(function(result) { + assert(!!(pAll instanceof Promise), 'The value of !!(pAll instanceof Promise) is expected to be true'); + assert(!!(result instanceof Array), 'The value of !!(result instanceof Array) is expected to be true'); + assert.sameValue(result.length, 1, 'The value of result.length is expected to be 1'); + assert.sameValue(result[0], 3, 'The value of result[0] is expected to be 3'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.2_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.2_T1.js new file mode 100644 index 0000000000..19e00ba2a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.2_T1.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all with 1-element array + should accept an array with settled promise +es6id: S25.4.4.1_A7.2_T1 +author: Sam Mikes +description: Promise.all() accepts a one-element array +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve({}); +}); + +sequence.push(1); + +Promise.all([p1]).then(function(resolved) { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "Expected Promise.all().then to queue second"); +}).catch($DONE); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "Expected p1.then to queue first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "Expected final then to queue last"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.1_T1.js new file mode 100644 index 0000000000..89e246e08e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.1_T1.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.1_A8.1_T1 +author: Sam Mikes +description: Promise.all([p1, p2]) resolution functions are called in predictable sequence +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve(1); +}); +var p2 = new Promise(function(resolve) { + resolve(2); +}); + +sequence.push(1); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "Expected to be called first."); +}).catch($DONE); + +Promise.all([p1, p2]).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "Expected to be called third."); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "Expected to be called second."); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js new file mode 100644 index 0000000000..d5ffb354d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js @@ -0,0 +1,26 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all with 2-element array +es6id: S25.4.4.1_A8.1_T1 +author: Sam Mikes +description: Promise.all() rejects when a promise in its array rejects +flags: [async] +---*/ + +var rejectP1, + p1 = new Promise(function(resolve, reject) { + rejectP1 = reject; + }), + p2 = Promise.resolve(2); + +Promise.all([p1, p2]).then(function(resolve) { + throw new Test262Error("Did not expect promise to be fulfilled."); +}, function(rejected) { + assert.sameValue(rejected, 1, 'The value of rejected is expected to be 1'); +}).then($DONE, $DONE); + +rejectP1(1); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js new file mode 100644 index 0000000000..71390b4c71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js @@ -0,0 +1,26 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.all with 2-element array +es6id: S25.4.4.1_A8.2_T2 +author: Sam Mikes +description: Promise.all() rejects when second promise in array rejects +flags: [async] +---*/ + +var rejectP2, + p1 = Promise.resolve(1), + p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; + }); + +Promise.all([p1, p2]).then(function() { + throw new Test262Error("Did not expect promise to be fulfilled."); +}, function(rejected) { + assert.sameValue(rejected, 2, 'The value of rejected is expected to be 2'); +}).then($DONE, $DONE); + +rejectP2(2); diff --git a/js/src/tests/test262/built-ins/Promise/all/browser.js b/js/src/tests/test262/built-ins/Promise/all/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-after-return.js b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-after-return.js new file mode 100644 index 0000000000..0204c9b790 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-after-return.js @@ -0,0 +1,55 @@ +// 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, Test262Error.thrower); +} +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()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-items.js b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-items.js new file mode 100644 index 0000000000..19d0ad3f45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element-items.js @@ -0,0 +1,52 @@ +// 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, Test262Error.thrower); +} +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()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/call-resolve-element.js b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element.js new file mode 100644 index 0000000000..c559e30e8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/call-resolve-element.js @@ -0,0 +1,45 @@ +// 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, Test262Error.thrower); +} +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()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/all/capability-executor-called-twice.js new file mode 100644 index 0000000000..992f6cb1c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/capability-executor-called-twice.js @@ -0,0 +1,104 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +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). + ... + + 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. + ... + + PerformPromiseAll ( iteratorRecord, constructor, resultCapability ) + + ... + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is *false*, throw a *TypeError* exception. + ... +---*/ + +var checkPoint = ""; +function fn1(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn1.resolve = function() {}; +Promise.all.call(fn1, []); +assert.sameValue(checkPoint, "abc", "executor initially called with no arguments"); + +checkPoint = ""; +function fn2(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn2.resolve = function() {}; +Promise.all.call(fn2, []); +assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)"); + +checkPoint = ""; +function fn3(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn3, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn3, []); +}, "executor initially called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)"); + +checkPoint = ""; +function fn4(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn4, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn4, []); +}, "executor initially called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)"); + +checkPoint = ""; +function fn5(executor) { + checkPoint += "a"; + executor("invalid value", 123); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn5, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn5, []); +}, "executor initially called with (String, Number)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/all/capability-executor-not-callable.js new file mode 100644 index 0000000000..7b2d1c1312 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/capability-executor-not-callable.js @@ -0,0 +1,109 @@ +// 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 = ""; +function fn1(executor) { + checkPoint += "a"; +} +Object.defineProperty(fn1, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn1, []); +}, "executor not called at all"); +assert.sameValue(checkPoint, "a", "executor not called at all"); + +checkPoint = ""; +function fn2(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; +} +Object.defineProperty(fn2, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn2, []); +}, "executor called with no arguments"); +assert.sameValue(checkPoint, "ab", "executor called with no arguments"); + +checkPoint = ""; +function fn3(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; +} +Object.defineProperty(fn3, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn3, []); +}, "executor called with (undefined, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)"); + +checkPoint = ""; +function fn4(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; +} +Object.defineProperty(fn4, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn4, []); +}, "executor called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)"); + +checkPoint = ""; +function fn5(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; +} +Object.defineProperty(fn5, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn5, []); +}, "executor called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)"); + +checkPoint = ""; +function fn6(executor) { + checkPoint += "a"; + executor(123, "invalid value"); + checkPoint += "b"; +} +Object.defineProperty(fn6, 'resolve', { + get() { throw new Test262Error; } +}); +assert.throws(TypeError, function() { + Promise.all.call(fn6, []); +}, "executor called with (Number, String)"); +assert.sameValue(checkPoint, "ab", "executor called with (Number, String)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-no-close.js new file mode 100644 index 0000000000..2be75cf0ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-no-close.js @@ -0,0 +1,79 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.all +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be ? NewPromiseCapability(C). + [...] + 7. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 8. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + d. If next is false, then + [...] + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « + valuesArray »). + + 25.4.1.1.1 IfAbruptRejectPromise + + IfAbruptRejectPromise is a short hand for a sequence of algorithm steps that + use a PromiseCapability Record. An algorithm step of the form: + + 1. IfAbruptRejectPromise(value, capability). + + means the same thing as: + + 1. If value is an abrupt completion, then + a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). + b. Return capability.[[Promise]]. + 2. Else if value is a Completion Record, let value be value.[[Value]]. +features: [Symbol.iterator] +---*/ + +var nextCount = 0; +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next: function() { + nextCount += 1; + return { + done: true + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw new Test262Error(); + }, reject); + }); +}; + +P.resolve = Promise.resolve; + +Promise.all.call(P, iter); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-reject.js b/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-reject.js new file mode 100644 index 0000000000..cae47e18f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/capability-resolve-throws-reject.js @@ -0,0 +1,68 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.all +description: > + Promise is rejected when the "resolve" capability returns an abrupt + completion. +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be ? NewPromiseCapability(C). + [...] + 7. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 8. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + d. If next is false, then + [...] + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « + valuesArray »). + + 25.4.1.1.1 IfAbruptRejectPromise + + IfAbruptRejectPromise is a short hand for a sequence of algorithm steps that + use a PromiseCapability Record. An algorithm step of the form: + + 1. IfAbruptRejectPromise(value, capability). + + means the same thing as: + + 1. If value is an abrupt completion, then + a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). + b. Return capability.[[Promise]]. + 2. Else if value is a Completion Record, let value be value.[[Value]]. +flags: [async] +---*/ + +var thrown = new Test262Error(); +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw thrown; + }, reject); + }); +}; + +P.resolve = Promise.resolve; + +Promise.all.call(P, []) + .then(function() { + $DONE('Promise incorrectly fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + $DONE('Promise rejected with incorrect "reason."'); + return; + } + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/all/ctx-ctor-throws.js new file mode 100644 index 0000000000..13de0ef9ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/ctx-ctor-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.all` invoked on a constructor value that throws an error +es6id: 25.4.4.1 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.all.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/all/ctx-ctor.js new file mode 100644 index 0000000000..b6fd1068a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/ctx-ctor.js @@ -0,0 +1,39 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.all` invoked on a constructor value +es6id: 25.4.4.1 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 10. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + [...] + 13. Return Completion(result). +features: [class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.all.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/all/ctx-non-ctor.js new file mode 100644 index 0000000000..d7206e5efb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.all` invoked on a non-constructor value +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +---*/ + +assert.throws(TypeError, function() { + Promise.all.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/all/ctx-non-object.js new file mode 100644 index 0000000000..decd8ad556 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.all` invoked on a non-object value +es6id: 25.4.4.1 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.all.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.all.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.all.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.all.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.all.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.all.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/does-not-invoke-array-setters.js b/js/src/tests/test262/built-ins/Promise/all/does-not-invoke-array-setters.js new file mode 100644 index 0000000000..9a7c4c3fde --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/does-not-invoke-array-setters.js @@ -0,0 +1,39 @@ +// |reftest| async +// 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. + ... +flags: [async] +---*/ + +Object.defineProperty(Array.prototype, 0, { + set: function() { + throw new Test262Error("Setter on Array.prototype called"); + } +}); + +Promise.all([42]).then(function() { + $DONE(); +}, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-close.js new file mode 100644 index 0000000000..58c50705d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-close.js @@ -0,0 +1,51 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error +esid: sec-promise.all +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + i. Let nextPromise be Invoke(constructor, "resolve", «nextValue»). + j. ReturnIfAbrupt(nextPromise ). +features: [Symbol.iterator] +---*/ + +var iterDoneSpy = {}; +var callCount = 0; +iterDoneSpy[Symbol.iterator] = function() { + return { + next: function() { + return { + value: null, + done: false + }; + }, + return: function() { + callCount += 1; + } + }; +}; + +Promise.resolve = function() { + throw new Test262Error(); +}; + +Promise.all(iterDoneSpy); + +assert.sameValue(callCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..e6a968cffe --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-error-reject.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error +esid: sec-promise.all +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + i. Let nextPromise be Invoke(constructor, "resolve", «nextValue»). + j. ReturnIfAbrupt(nextPromise ). +flags: [async] +---*/ + +var thrown = new Test262Error(); +Promise.resolve = function() { + throw thrown; +}; + +Promise.all([1]) + .then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + throw new Test262Error('The promise should be rejected with the thrown error object'); + } + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..037b999b71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error-reject.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (rejecting promise) +esid: sec-performpromiseall +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + Runtime Semantics: PerformPromiseAll + + ... + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + ... + 1. Repeat, + 1. Let next be IteratorStep(iteratorRecord). + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, < nextValue >). +flags: [async] +---*/ + +var error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get: function() { + throw error; + } +}); + +Promise.all([new Promise(function() {})]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error.js new file mode 100644 index 0000000000..4bfc0a8afb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.all ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.all(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..1789a4a30b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.all +info: | + Runtime Semantics: PerformPromiseAll + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var p1 = Promise.resolve(1); +var p2 = Promise.resolve(1); +var p3 = Promise.reject(1); +var p4 = Promise.resolve(1); +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.all([p1, p2, p3, p4]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 4, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..ec86fba799 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.all +info: | + Runtime Semantics: PerformPromiseAll + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.all([]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 0, '`resolve` not called for empty iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..84855dc903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.all +info: | + Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAll + + Repeat + ... + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.all.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..14f562465a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.all +info: | + Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAll + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1,1,1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.all(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..2e5b928f51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.all +info: | + Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAll + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.all(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every iterated value'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-return.js new file mode 100644 index 0000000000..6f63505b7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve-return.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + i. Let nextPromise be Invoke(constructor, "resolve", «nextValue»). + [...] + r. Let result be Invoke(nextPromise, "then", resolveElement, + promiseCapability.[[Reject]]»). + [...] +---*/ + +var originalCallCount = 0; +var newCallCount = 0; +var P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +var originalThenable = { + then: function() { + originalCallCount += 1; + } +}; +var newThenable = { + then: function() { + newCallCount += 1; + } +}; + +Promise.all.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve.js new file mode 100644 index 0000000000..448bf9e22e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-resolve.js @@ -0,0 +1,54 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +es6id: 25.4.4.1 +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + i. Let nextPromise be Invoke(constructor, "resolve", «nextValue»). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var resolve = Promise.resolve; +var callCount = 0; +var current = p1; +var next = p2; +var afterNext = p3; + +Promise.resolve = function(nextValue) { + assert.sameValue( + nextValue, current, '`resolve` invoked with next iterated value' + ); + assert.sameValue( + arguments.length, 1, '`resolve` invoked with a single argument' + ); + assert.sameValue(this, Promise, '`this` value is the constructor'); + + current = next; + next = afterNext; + afterNext = null; + + callCount += 1; + + return resolve.apply(Promise, arguments); +}; + +Promise.all([p1, p2, p3]); + +assert.sameValue( + callCount, 3, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-close.js new file mode 100644 index 0000000000..fffd528d2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-close.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-performpromiseall +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", «resolveElement, + resultCapability.[[Reject]]»). + s. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +promise.then = function() { + throw new Test262Error(); +}; + +Promise.all(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-reject.js new file mode 100644 index 0000000000..4e91208d87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-then-error-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting Promise) +esid: sec-performpromiseall +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", «resolveElement, + resultCapability.[[Reject]]»). + s. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +promise.then = function() { + throw error; +}; + +Promise.all([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-close.js new file mode 100644 index 0000000000..7a5b7ce446 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-close.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accesing the instance's `then` method (closing iterator) +esid: sec-performpromiseall +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", «resolveElement, + resultCapability.[[Reject]]»). + s. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +Object.defineProperty(promise, 'then', { + get: function() { + throw new Test262Error(); + } +}); + +Promise.all(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..6f5fa60bf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-then-get-error-reject.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting Promise) +esid: sec-performpromiseall +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", «resolveElement, + resultCapability.[[Reject]]»). + s. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +Object.defineProperty(promise, 'then', { + get: function() { + throw error; + } +}); + +Promise.all([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/invoke-then.js b/js/src/tests/test262/built-ins/Promise/all/invoke-then.js new file mode 100644 index 0000000000..80113deb33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/invoke-then.js @@ -0,0 +1,57 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +es6id: 25.4.4.1 +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", «resolveElement, + resultCapability.[[Reject]]»). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var callCount = 0; +var currentThis = p1; +var nextThis = p2; +var afterNextThis = p3; + +p1.then = p2.then = p3.then = function(a, b) { + assert.sameValue(typeof a, 'function', 'type of first argument'); + assert.sameValue( + a.length, + 1, + 'ES6 25.4.1.3.2: The length property of a promise resolve function is 1.' + ); + assert.sameValue(typeof b, 'function', 'type of second argument'); + assert.sameValue( + b.length, + 1, + 'ES6 25.4.1.3.1: The length property of a promise reject function is 1.' + ); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + assert.sameValue(this, currentThis, '`this` value'); + + currentThis = nextThis; + nextThis = afterNextThis; + afterNextThis = null; + + callCount += 1; +}; + +Promise.all([p1, p2, p3]); + +assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..258cc45054 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-false-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is `false` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..a527580294 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-null-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is `null` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..0bfee0b2f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-number-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..c20288b677 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-string-resolve.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Resolve when argument is a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all("").then(function(v) { + assert.sameValue(v.length, 0); + }, function() { + $DONE('The promise should be resolved, but was rejected'); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..b3c22c06de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-symbol-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..9c62656960 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-true-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is `true` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..9e9459776a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-arg-is-undefined-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument is `undefined` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-false-reject.js new file mode 100644 index 0000000000..09f3b39bf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-false-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-null-reject.js new file mode 100644 index 0000000000..ce77efa446 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-null-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-number-reject.js new file mode 100644 index 0000000000..4c63977bc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-number-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-string-reject.js new file mode 100644 index 0000000000..8f23475cd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-string-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: "" + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..1eaa109428 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-symbol-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-true-reject.js new file mode 100644 index 0000000000..172235e9ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-true-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..9d8e741728 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-assigned-undefined-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..ad0d763ace --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-no-close.js @@ -0,0 +1,57 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +---*/ + +var iterNextValThrows = {}; +var returnCount = 0; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.all(iterNextValThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-reject.js new file mode 100644 index 0000000000..b8dabaa0d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-next-val-err-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Error when accessing an iterator result's `value` property (rejecting + promise) +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + } + }; +}; + +Promise.all(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-false-reject.js new file mode 100644 index 0000000000..68c9b42031 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-false-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return false; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-null-reject.js new file mode 100644 index 0000000000..f0f8c80cc3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-null-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return null; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-number-reject.js new file mode 100644 index 0000000000..0b130ef77e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-number-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return 1; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-string-reject.js new file mode 100644 index 0000000000..37dd3692b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-string-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return ""; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..023ef1f66a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-symbol-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return Symbol(); + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-true-reject.js new file mode 100644 index 0000000000..4211c8d1ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-true-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return true; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..3ed1c633d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-returns-undefined-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.all({ + [Symbol.iterator]() { + return undefined; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/all/iter-step-err-no-close.js new file mode 100644 index 0000000000..e0f9b679aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-step-err-no-close.js @@ -0,0 +1,59 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Error when advancing the provided iterable (not closing iterator) +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to + true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var returnCount = 0; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + throw new Test262Error('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.all(iterStepThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/all/iter-step-err-reject.js new file mode 100644 index 0000000000..0f927aac75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/iter-step-err-reject.js @@ -0,0 +1,56 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Error when advancing the provided iterable (rejecting promise) +info: | + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + + [...] + 6. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to + true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + $DONE('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + } + }; +}; + +Promise.all(iterStepThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/length.js b/js/src/tests/test262/built-ins/Promise/all/length.js new file mode 100644 index 0000000000..7769497c7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.1 +description: Promise.all `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.all.length, 1); + +verifyNotEnumerable(Promise.all, 'length'); +verifyNotWritable(Promise.all, 'length'); +verifyConfigurable(Promise.all, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/name.js b/js/src/tests/test262/built-ins/Promise/all/name.js new file mode 100644 index 0000000000..552ba841dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.1 +description: Promise.all `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.all.name, 'all'); + +verifyNotEnumerable(Promise.all, 'name'); +verifyNotWritable(Promise.all, 'name'); +verifyConfigurable(Promise.all, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/new-resolve-function.js b/js/src/tests/test262/built-ins/Promise/all/new-resolve-function.js new file mode 100644 index 0000000000..9d668f67e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/new-resolve-function.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.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, Test262Error.thrower); +} +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/all/not-a-constructor.js new file mode 100644 index 0000000000..9ab0f8e49e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.all does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.all), false, 'isConstructor(Promise.all) must return false'); + +assert.throws(TypeError, () => { + new Promise.all([]); +}, '`new Promise.all([])` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/prop-desc.js b/js/src/tests/test262/built-ins/Promise/all/prop-desc.js new file mode 100644 index 0000000000..b40599802b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright 2015 Jordan Harband. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: 25.4.4.1_A1.3_T1 +author: Jordan Harband +description: Promise.all property descriptor +info: | + ES6 Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'all'); +verifyWritable(Promise, 'all'); +verifyConfigurable(Promise, 'all'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/all/reject-deferred.js new file mode 100644 index 0000000000..c439bcaf75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/reject-deferred.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", resolveElement, + promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(); + }); + } +}; + +Promise.all([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function(x) { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/all/reject-ignored-deferred.js new file mode 100644 index 0000000000..482a48b0a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/reject-ignored-deferred.js @@ -0,0 +1,59 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", resolveElement, + promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(); + }); + } +}; +var rejector = { + then: function(resolve, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(); + reject(); + }); + } +}; + +Promise.all([fulfiller, rejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/all/reject-ignored-immed.js new file mode 100644 index 0000000000..3a8b8ebd62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/reject-ignored-immed.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", resolveElement, + promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + resolve(); + } +}; +var lateRejector = { + then: function(resolve, reject) { + resolve(); + reject(); + } +}; + +Promise.all([fulfiller, lateRejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/reject-immed.js b/js/src/tests/test262/built-ins/Promise/all/reject-immed.js new file mode 100644 index 0000000000..4c476081ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/reject-immed.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through immediate invocation of the provided resolving function +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + r. Let result be Invoke(nextPromise, "then", resolveElement, + promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + reject(); + } +}; + +Promise.all([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function(x) { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit-from-same.js b/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit-from-same.js new file mode 100644 index 0000000000..54705cb2fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit-from-same.js @@ -0,0 +1,75 @@ +// 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, Test262Error.thrower); +} +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit.js b/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit.js new file mode 100644 index 0000000000..7ba90e2d9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-before-loop-exit.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 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, Test262Error.thrower); +} +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()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-extensible.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-extensible.js new file mode 100644 index 0000000000..5b0a6b0218 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-extensible.js @@ -0,0 +1,30 @@ +// 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: The [[Extensible]] slot of Promise.all Resolve Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +assert(Object.isExtensible(resolveElementFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-length.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-length.js new file mode 100644 index 0000000000..6a3568870b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-length.js @@ -0,0 +1,38 @@ +// 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: The `length` property of Promise.all Resolve Element functions +info: | + The length property of a Promise.all resolve element function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +assert.sameValue(resolveElementFunction.length, 1); + +verifyNotEnumerable(resolveElementFunction, "length"); +verifyNotWritable(resolveElementFunction, "length"); +verifyConfigurable(resolveElementFunction, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-name.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-name.js new file mode 100644 index 0000000000..cb30b5a007 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-name.js @@ -0,0 +1,40 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all-resolve-element-functions +description: The `name` property of Promise.all Resolve Element functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +verifyProperty(resolveElementFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-nonconstructor.js new file mode 100644 index 0000000000..14c832f80c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-nonconstructor.js @@ -0,0 +1,34 @@ +// 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: Promise.all Resolve Element functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(resolveElementFunction, "prototype"), false); +assert.throws(TypeError, function() { + new resolveElementFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-property-order.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-property-order.js new file mode 100644 index 0000000000..a8bcc951de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-property-order.js @@ -0,0 +1,32 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise.all resolve element function property order +info: | + Set order: "length", "name" +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +var propNames = Object.getOwnPropertyNames(resolveElementFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-prototype.js b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-prototype.js new file mode 100644 index 0000000000..7daca24a61 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-element-function-prototype.js @@ -0,0 +1,32 @@ +// 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: The [[Prototype]] of Promise.all Resolve Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.all.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(resolveElementFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/all/resolve-from-same-thenable.js new file mode 100644 index 0000000000..1a788c624c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-from-same-thenable.js @@ -0,0 +1,81 @@ +// 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, Test262Error.thrower); +} +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..3b8f52a09a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.any +info: | + Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAll + + Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [arrow-function] +---*/ + +var resolver = { + then(resolve) { + new Promise((resolve) => resolve()) + .then(() => resolve(42)); + } +}; +var lateRejector = { + then(resolve, reject) { + new Promise((resolve) => resolve()) + .then(() => { + resolve(9); + reject(); + }); + } +}; + +Promise.all([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution[0], 42); + assert.sameValue(resolution[1], 9); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..cb830c90ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-ignores-late-rejection.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.all +info: | + Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAll + + Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [arrow-function] +---*/ + +var resolver = { + then(resolve) { + resolve(42); + } +}; +var lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.all([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution[0], 42); + assert.sameValue(resolution[1], 33); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/all/resolve-non-callable.js new file mode 100644 index 0000000000..8807b8fc60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.all ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.all(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/all/resolve-non-thenable.js new file mode 100644 index 0000000000..76c1781fd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-non-thenable.js @@ -0,0 +1,76 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + d. If next is false, + [...] + iii. If remainingElementsCount.[[value]] is 0, + 1. Let valuesArray be CreateArrayFromList(values). + 2. Let resolveResult be Call(resultCapability.[[Resolve]], + undefined, «valuesArray»). + 3. ReturnIfAbrupt(resolveResult) + iv. Return resultCapability.[[Promise]]. + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var v1 = {}; +var v2 = {}; +var v3 = {}; + +Promise.all([v1, v2, v3]) + .then(function(values) { + if (!values) { + $DONE('The promise should be resolved with a value.'); + return; + } + if (values.constructor !== Array) { + $DONE('The promise should be resolved with an Array instance.'); + return; + } + + if (values.length !== 3) { + $DONE('The promise should be resolved with an array of proper length.'); + return; + } + + if (values[0] !== v1) { + $DONE('The promise should be resolved with the correct element values (#1)'); + return; + } + + if (values[1] !== v2) { + $DONE('The promise should be resolved with the correct element values (#2)'); + return; + } + + if (values[2] !== v3) { + $DONE('The promise should be resolved with the correct element values (#3)'); + return; + } + + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-not-callable-reject-with-typeerror.js b/js/src/tests/test262/built-ins/Promise/all/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 0000000000..c310818802 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.all +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + Let promiseResolve be ? Get(constructor, "resolve"). + If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + +flags: [async] +features: [arrow-function] +---*/ + +Promise.resolve = null; + +Promise.all([1]) + .then( + () => $DONE('The promise should not be resolved.'), + error => { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/all/resolve-poisoned-then.js new file mode 100644 index 0000000000..d877f7d3da --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-poisoned-then.js @@ -0,0 +1,72 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + d. If next is false, + [...] + iii. If remainingElementsCount.[[value]] is 0, + 1. Let valuesArray be CreateArrayFromList(values). + 2. Let resolveResult be Call(resultCapability.[[Resolve]], + undefined, «valuesArray»). + 3. ReturnIfAbrupt(resolveResult) + iv. Return resultCapability.[[Promise]]. + + 7.3.16 CreateArrayFromList (elements) + [...] + 2. Let array be ArrayCreate(0) (see 9.4.2.2). + + 9.4.2.2 ArrayCreate(length, proto) + [...] + 4. If the proto argument was not passed, let proto be the intrinsic object + %ArrayPrototype%. + 5. Let A be a newly created Array exotic object. + [...] + 8. Set the [[Prototype]] internal slot of A to proto. + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var promise; + +try { + Object.defineProperty(Array.prototype, 'then', { + get: function() { + throw value; + }, + configurable: true + }); + + promise = Promise.all([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the expected value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/all/resolve-thenable.js b/js/src/tests/test262/built-ins/Promise/all/resolve-thenable.js new file mode 100644 index 0000000000..5fd1b42ee0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/resolve-thenable.js @@ -0,0 +1,74 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability). + [...] + + 25.4.4.1.1 Runtime Semantics: PerformPromiseAll + [...] + 6. Repeat + [...] + d. If next is false, + [...] + iii. If remainingElementsCount.[[value]] is 0, + 1. Let valuesArray be CreateArrayFromList(values). + 2. Let resolveResult be Call(resultCapability.[[Resolve]], + undefined, «valuesArray»). + 3. ReturnIfAbrupt(resolveResult) + iv. Return resultCapability.[[Promise]]. + + 7.3.16 CreateArrayFromList (elements) + [...] + 2. Let array be ArrayCreate(0) (see 9.4.2.2). + + 9.4.2.2 ArrayCreate(length, proto) + [...] + 4. If the proto argument was not passed, let proto be the intrinsic object + %ArrayPrototype%. + 5. Let A be a newly created Array exotic object. + [...] + 8. Set the [[Prototype]] internal slot of A to proto. + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var promise; + +try { + Array.prototype.then = function(resolve) { + resolve(value); + }; + + promise = Promise.all([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the expected value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/all/same-reject-function.js b/js/src/tests/test262/built-ins/Promise/all/same-reject-function.js new file mode 100644 index 0000000000..4112672a03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/same-reject-function.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.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(Test262Error.thrower, rejectFunction); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; + +var p1 = { + then: function(onFulfilled, onRejected) { + callCount1 += 1; + assert.sameValue(onRejected, rejectFunction, "p1.then"); + } +}; +var p2 = { + then: function(onFulfilled, onRejected) { + callCount2 += 1; + assert.sameValue(onRejected, rejectFunction, "p2.then"); + } +}; + +Promise.all.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, "p1.then call count"); +assert.sameValue(callCount2, 1, "p2.then call count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/shell.js b/js/src/tests/test262/built-ins/Promise/all/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/all/species-get-error.js b/js/src/tests/test262/built-ins/Promise/all/species-get-error.js new file mode 100644 index 0000000000..2c4597bcab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/all/species-get-error.js @@ -0,0 +1,29 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.all() does not retrieve `Symbol.species` property of the `this` value +es6id: 25.4.4.1 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... +features: [Symbol.species] +---*/ + +function C(executor) { + executor(function() {}, function() {}); +} + +C.resolve = function() {}; +Object.defineProperty(C, Symbol.species, { + get: function() { + throw new Test262Error("Getter for Symbol.species called"); + } +}); + +Promise.all.call(C, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/browser.js b/js/src/tests/test262/built-ins/Promise/allSettled/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-after-return.js b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-after-return.js new file mode 100644 index 0000000000..bfc4795f8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-after-return.js @@ -0,0 +1,57 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled element after Promise.allSettled() returned. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; +var valuesArray; +var expected = [{ status: 'fulfilled', value: 'expectedValue' }]; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + valuesArray = values; + checkSettledPromises(values, expected, 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + onFulfilled('expectedValue'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); +checkSettledPromises(valuesArray, expected, 'valuesArray after call to all()'); + +p1OnFulfilled('unexpectedValue'); + +assert.sameValue(callCount, 1, 'callCount after call to onFulfilled()'); +checkSettledPromises(valuesArray, expected, 'valuesArray after call to onFulfilled()'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-items.js b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-items.js new file mode 100644 index 0000000000..a49adfa8e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element-items.js @@ -0,0 +1,61 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled elements. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'expectedValue-p1' + }, + { + status: 'fulfilled', + value: 'expectedValue-p2' + } + ], 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue-p1'); + onFulfilled('unexpectedValue-p1'); + } +}; +var p2 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue-p2'); + onFulfilled('unexpectedValue-p2'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element.js b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element.js new file mode 100644 index 0000000000..511b3a14b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/call-resolve-element.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled element. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'expectedValue' + } + ], 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue'); + onFulfilled('unexpectedValue'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-called-twice.js new file mode 100644 index 0000000000..9380bda0f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-called-twice.js @@ -0,0 +1,108 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.allSettled ( iterable ) + + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + + GetCapabilitiesExecutor Functions + + ... + 4. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception. + 5. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception. + 6. Set promiseCapability.[[Resolve]] to resolve. + 7. Set promiseCapability.[[Reject]] to reject. + ... +features: [Promise.allSettled] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn1.resolve = function() { + throw new Test262Error(); +}; +Promise.allSettled.call(fn1, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with no arguments'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn2.resolve = function() { + throw new Test262Error(); +}; +Promise.allSettled.call(fn2, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with (undefined, undefined)'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn3, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn3, []); +}, 'executor initially called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (undefined, function)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn4, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn4, []); +}, 'executor initially called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (function, undefined)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor('invalid value', 123); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn5, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn5, []); +}, 'executor initially called with (String, Number)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (String, Number)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-not-callable.js new file mode 100644 index 0000000000..02a29909b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/capability-executor-not-callable.js @@ -0,0 +1,109 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.allSettled ( iterable ) + + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + + NewPromiseCapability ( C ) + + ... + 5. Let executor be CreateBuiltinFunction(steps, « [[Capability]] »). + 6. Set executor.[[Capability]] to promiseCapability. + 7. Let promise be ? Construct(C, « executor »). + 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception. + 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception. + ... +features: [Promise.allSettled] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; +} +Object.defineProperty(fn1, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn1, []); +}, 'executor not called at all'); +assert.sameValue(checkPoint, 'a', 'executor not called at all'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; +} +Object.defineProperty(fn2, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn2, []); +}, 'executor called with no arguments'); +assert.sameValue(checkPoint, 'ab', 'executor called with no arguments'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn3, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn3, []); +}, 'executor called with (undefined, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, undefined)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; +} +Object.defineProperty(fn4, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn4, []); +}, 'executor called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, function)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn5, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn5, []); +}, 'executor called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (function, undefined)'); + +checkPoint = ''; +function fn6(executor) { + checkPoint += 'a'; + executor(123, 'invalid value'); + checkPoint += 'b'; +} +Object.defineProperty(fn6, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.allSettled.call(fn6, []); +}, 'executor called with (Number, String)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (Number, String)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js new file mode 100644 index 0000000000..e59ca8916e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js @@ -0,0 +1,66 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.allsettled +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + d. If next is false, then + ... + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + + IfAbruptRejectPromise + + 1. IfAbruptRejectPromise(value, capability). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: true + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw new Test262Error(); + }, reject); + }); +}; + +P.resolve = function() { + throw new Test262Error(); +}; + +Promise.allSettled.call(P, iter); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-reject.js new file mode 100644 index 0000000000..5e02b835d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/capability-resolve-throws-reject.js @@ -0,0 +1,60 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.allsettled +description: > + Promise is rejected when the "resolve" capability returns an abrupt + completion. +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + d. If next is false, then + ... + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + + + IfAbruptRejectPromise + + 1. IfAbruptRejectPromise(value, capability). +flags: [async] +features: [Promise.allSettled] +---*/ + +var thrown = new Test262Error(); +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw thrown; + }, reject); + }); +}; + +P.resolve = function() { + throw new Test262Error(); +}; + +Promise.allSettled.call(P, []) + .then(function() { + $DONE('Promise incorrectly fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + $DONE('Promise rejected with incorrect "reason."'); + return; + } + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor-throws.js new file mode 100644 index 0000000000..322690025e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor-throws.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a constructor value that throws an error +esid: sec-promise.allsettled +info: | + 3. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability + + ... + 7. Let promise be ? Construct(C, « executor »). +features: [Promise.allSettled] +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.allSettled.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor.js new file mode 100644 index 0000000000..66fa8d387b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-ctor.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a constructor value +esid: sec-promise.allsettled +info: | + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + ... + 8. Return Completion(result). +features: [Promise.allSettled, class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.allSettled.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-ctor.js new file mode 100644 index 0000000000..3850884632 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a non-constructor value +esid: sec-promise.allsettled +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +features: [Promise.allSettled] +---*/ + +assert.throws(TypeError, function() { + Promise.allSettled.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-object.js new file mode 100644 index 0000000000..a44e2ba28b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a non-object value +esid: sec-promise.allsettled +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Promise.allSettled, Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.allSettled.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/does-not-invoke-array-setters.js b/js/src/tests/test262/built-ins/Promise/allSettled/does-not-invoke-array-setters.js new file mode 100644 index 0000000000..7105446411 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/does-not-invoke-array-setters.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Indexed setter properties on Array.prototype are not invoked. +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b, IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled ( 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. + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +Object.defineProperty(Array.prototype, 0, { + set() { + throw new Test262Error('Setter on Array.prototype called'); + } +}); + +Promise.allSettled([42]).then(function() { + $DONE(); +}, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-close.js new file mode 100644 index 0000000000..8855a5e989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-close.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterDoneSpy = {}; +var callCount = 0; +iterDoneSpy[Symbol.iterator] = function() { + return { + next() { + return { + value: null, + done: false + }; + }, + return() { + callCount += 1; + } + }; +}; + +Promise.resolve = function() { + throw new Error(); +}; + +Promise.allSettled(iterDoneSpy); + +assert.sameValue(callCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..8d44515c1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-error-reject.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var thrown = new Test262Error(); +Promise.resolve = function() { + throw thrown; +}; + +Promise.allSettled([1]) + .then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + throw new Test262Error('The promise should be rejected with the thrown error object'); + } + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..ffc8525c37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (rejecting promise) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get() { + throw error; + } +}); + +Promise.allSettled([new Promise(function() {})]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error.js new file mode 100644 index 0000000000..c4e560b61e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.allSettled ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Promise.allSettled, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.allSettled(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..9dc562bb57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Let promiseResolve be ? Get(constructor, `"resolve"`). + 7. 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +features: [Promise.allSettled] +---*/ + +var p1 = Promise.resolve(1); +var p2 = Promise.resolve(1); +var p3 = Promise.reject(1); +var p4 = Promise.resolve(1); +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.allSettled([p1, p2, p3, p4]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 4, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..1be9e774be --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,45 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Let promiseResolve be ? Get(constructor, `"resolve"`). + 7. 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +features: [Promise.allSettled] +---*/ + +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.allSettled([]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 0, '`resolve` not called for empty iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..46502e00ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.allSettled +info: | + 7. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 7. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.allSettled, class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.allSettled.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..52e8992abb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.allSettled +info: | + 7. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 7. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.allSettled, arrow-function] +---*/ + +let values = [1,1,1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.allSettled(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..2c8678c381 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.allSettled +info: | + 5. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.allSettled, arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.allSettled(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every iterated value'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-return.js new file mode 100644 index 0000000000..99d28cde15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve-return.js @@ -0,0 +1,44 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var originalCallCount = 0; +var newCallCount = 0; +var P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +var originalThenable = { + then() { + originalCallCount += 1; + } +}; +var newThenable = { + then() { + newCallCount += 1; + } +}; + +Promise.allSettled.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve.js new file mode 100644 index 0000000000..c7f500609f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-resolve.js @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var resolve = Promise.resolve; +var callCount = 0; +var current = p1; +var next = p2; +var afterNext = p3; + +Promise.resolve = function(nextValue) { + assert.sameValue( + nextValue, current, '`resolve` invoked with next iterated value' + ); + assert.sameValue( + arguments.length, 1, '`resolve` invoked with a single argument' + ); + assert.sameValue(this, Promise, '`this` value is the constructor'); + + current = next; + next = afterNext; + afterNext = null; + + callCount += 1; + + return resolve.apply(Promise, arguments); +}; + +Promise.allSettled([p1, p2, p3]); + +assert.sameValue( + callCount, 3, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-close.js new file mode 100644 index 0000000000..68134047a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-close.js @@ -0,0 +1,45 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +promise.then = function() { + throw new Test262Error(); +}; + +Promise.allSettled(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-reject.js new file mode 100644 index 0000000000..a6b1e70670 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-error-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting Promise) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +promise.then = function() { + throw error; +}; + +Promise.allSettled([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-close.js new file mode 100644 index 0000000000..e5bf42c056 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-close.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accesing the instance's `then` method (closing iterator) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Object.defineProperty(promise, 'then', { + get() { + throw new Test262Error(); + } +}); + +Promise.allSettled(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..53fc2ab99d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then-get-error-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting Promise) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.allSettled([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then.js b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then.js new file mode 100644 index 0000000000..e042be9470 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/invoke-then.js @@ -0,0 +1,55 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var callCount = 0; +var currentThis = p1; +var nextThis = p2; +var afterNextThis = p3; + +p1.then = p2.then = p3.then = function(a, b) { + assert.sameValue(typeof a, 'function', 'type of first argument'); + assert.sameValue( + a.length, + 1, + 'The length property of a promise resolve function is 1.' + ); + assert.sameValue(typeof b, 'function', 'type of second argument'); + assert.sameValue( + b.length, + 1, + 'The length property of a promise reject function is 1.' + ); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + assert.sameValue(this, currentThis, '`this` value'); + + currentThis = nextThis; + nextThis = afterNextThis; + afterNextThis = null; + + callCount += 1; +}; + +Promise.allSettled([p1, p2, p3]); + +assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/is-function.js b/js/src/tests/test262/built-ins/Promise/allSettled/is-function.js new file mode 100644 index 0000000000..daf7e13c23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/is-function.js @@ -0,0 +1,12 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled is callable +features: [Promise.allSettled] +---*/ + +assert.sameValue(typeof Promise.allSettled, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..922a04af41 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-false-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `false` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..b168fd1bb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-null-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `null` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..1acd2b92f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-number-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is a number +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-poisoned.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-poisoned.js new file mode 100644 index 0000000000..0062464619 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-poisoned.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject with abrupt completion from GetIterator +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var poison = []; +var error = new Test262Error(); +Object.defineProperty(poison, Symbol.iterator, { + get() { + throw error; + } +}); + +try { + Promise.allSettled(poison).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(err) { + assert.sameValue(err, error); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..44b36a28b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolve when argument is a string +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled('').then(function(v) { + assert.sameValue(v.length, 0); + }, function() { + $DONE('The promise should be resolved, but was rejected'); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..d5a8f6ab23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is a symbol +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..938a896bed --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-true-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `true` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..fb06afbe2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `undefined` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-false-reject.js new file mode 100644 index 0000000000..f6f0480626 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-false-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + i. Set method to ? GetMethod(obj, @@asyncIterator). + ii. If method is undefined, then + 1. Let syncMethod be ? GetMethod(obj, @@iterator). + 2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod). + ... + 4. Let iterator be ? Call(method, obj). + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-null-reject.js new file mode 100644 index 0000000000..920c1014ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-null-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-number-reject.js new file mode 100644 index 0000000000..6aa69307e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-number-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-string-reject.js new file mode 100644 index 0000000000..4154d30463 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-string-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: '' + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..63797534c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-true-reject.js new file mode 100644 index 0000000000..e7edd2e6c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-true-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..6ab397c63d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-err-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-err-reject.js new file mode 100644 index 0000000000..11c0bc77ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-err-reject.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when call an iterator next step (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + ... + + IteratorStep ( iteratorRecord ) + + 1. Let result be ? IteratorNext(iteratorRecord). + + IteratorNext ( iteratorRecord [ , value ] ) + + 1. If value is not present, then + a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « »). + 2. Else, + a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »). + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var error = new Test262Error(); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + throw error; + } + }; +}; + +Promise.allSettled(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..368c72d590 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-no-close.js @@ -0,0 +1,58 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + g. ReturnIfAbrupt(nextValue). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterNextValThrows = {}; +var returnCount = 0; +var nextCount = 0; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + nextCount += 1; + return poisonedVal; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.allSettled(iterNextValThrows); + +assert.sameValue(returnCount, 0); +assert.sameValue(nextCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-reject.js new file mode 100644 index 0000000000..a5855e5efb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-next-val-err-reject.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when accessing an iterator result's `value` property (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + g. ReturnIfAbrupt(nextValue). +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedVal; + } + }; +}; + +Promise.allSettled(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-false-reject.js new file mode 100644 index 0000000000..61ade03c35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-false-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns false +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return false; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-null-reject.js new file mode 100644 index 0000000000..06772c0d74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-null-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns null +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return null; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-number-reject.js new file mode 100644 index 0000000000..4a49159127 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-number-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a number +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 1; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-string-reject.js new file mode 100644 index 0000000000..85094a5763 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-string-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a string +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return ''; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..2a31e898f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-symbol-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a symbol +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return Symbol(); + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-true-reject.js new file mode 100644 index 0000000000..4a31be5163 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-true-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns true +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return true; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..48dd3c1ba7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-returns-undefined-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return undefined; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-no-close.js new file mode 100644 index 0000000000..c7c988138b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-no-close.js @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when advancing the provided iterable (not closing iterator) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var returnCount = 0; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get() {} +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedDone; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.allSettled(iterStepThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-reject.js new file mode 100644 index 0000000000..874f3018e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/iter-step-err-reject.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when advancing the provided iterable (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get() { + $DONE('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedDone; + } + }; +}; + +Promise.allSettled(iterStepThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/length.js b/js/src/tests/test262/built-ins/Promise/allSettled/length.js new file mode 100644 index 0000000000..c0ffb02fb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled `length` property +info: | + ES Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +verifyProperty(Promise.allSettled, 'length', { + configurable: true, + writable: false, + enumerable: false, + value: 1, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/name.js b/js/src/tests/test262/built-ins/Promise/allSettled/name.js new file mode 100644 index 0000000000..fe9c2497d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/name.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled `name` property +info: | + ES Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +verifyProperty(Promise.allSettled, 'name', { + configurable: true, + writable: false, + enumerable: false, + value: 'allSettled', +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/new-reject-function.js b/js/src/tests/test262/built-ins/Promise/allSettled/new-reject-function.js new file mode 100644 index 0000000000..16e4ed0e2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/new-reject-function.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Each Promise.allSettled element is called with a new Promise.allSettled Reject Element function. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + ... +features: [Promise.allSettled] +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(rejectFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; +var p1OnRejected; + +var p1 = { + then(_, onRejected) { + callCount1 += 1; + p1OnRejected = onRejected; + assert.notSameValue(onRejected, rejectFunction, 'p1.then'); + } +}; +var p2 = { + then(_, onRejected) { + callCount2 += 1; + assert.notSameValue(onRejected, rejectFunction, 'p2.then'); + assert.notSameValue(onRejected, p1OnRejected, 'p1.onRejected != p2.onRejected'); + } +}; + +Promise.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/new-resolve-function.js b/js/src/tests/test262/built-ins/Promise/allSettled/new-resolve-function.js new file mode 100644 index 0000000000..048d664dc2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/new-resolve-function.js @@ -0,0 +1,52 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Each Promise.allSettled element is called with a new Promise.allSettled Resolve Element function. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + ... + k Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + ... +features: [Promise.allSettled] +---*/ + +function resolveFunction() {} + +function Constructor(executor) { + executor(resolveFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + callCount1 += 1; + p1OnFulfilled = onFulfilled; + assert.notSameValue(onFulfilled, resolveFunction, 'p1.then'); + } +}; +var p2 = { + then(onFulfilled, onRejected) { + callCount2 += 1; + assert.notSameValue(onFulfilled, resolveFunction, 'p2.then'); + assert.notSameValue(onFulfilled, p1OnFulfilled, 'p1.onFulfilled != p2.onFulfilled'); + } +}; + +Promise.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/allSettled/not-a-constructor.js new file mode 100644 index 0000000000..98dc3d6401 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.allSettled does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Promise.allSettled, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.allSettled), false, 'isConstructor(Promise.allSettled) must return false'); + +assert.throws(TypeError, () => { + new Promise.allSettled(); +}, '`new Promise.allSettled()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/prop-desc.js b/js/src/tests/test262/built-ins/Promise/allSettled/prop-desc.js new file mode 100644 index 0000000000..46ae80be70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/prop-desc.js @@ -0,0 +1,23 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled property descriptor +info: | + ES Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +verifyProperty(Promise, 'allSettled', { + configurable: true, + writable: true, + enumerable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-deferred.js new file mode 100644 index 0000000000..6eec5d809b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-deferred.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; +var thenable = { + then(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(simulation); + }); + } +}; + +Promise.allSettled([thenable]) + .then((settleds) => { + assert.sameValue(settleds.length, 1); + assert.sameValue(settleds[0].status, 'rejected'); + assert.sameValue(settleds[0].reason, simulation); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-extensible.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-extensible.js new file mode 100644 index 0000000000..5672b6e9dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-extensible.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The [[Extensible]] slot of Promise.allSettled Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert(Object.isExtensible(rejectElementFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-length.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-length.js new file mode 100644 index 0000000000..9c92566180 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-length.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The `length` property of Promise.allSettled Reject Element functions +info: | + The length property of a Promise.allSettled Reject Element function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(rejectElementFunction.length, 1); + +verifyProperty(rejectElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-multiple-calls.js new file mode 100644 index 0000000000..2cbc89007d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-multiple-calls.js @@ -0,0 +1,56 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper with remainingElementsCount when Promise.allSettled reject element function is called multiple times. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, ) + + If alreadyCalled.[[Value]] is true, return undefined. + +features: [Promise.allSettled] +---*/ + +let rejectCallCount = 0; +let returnValue = {}; +let error = new Test262Error(); + +function Constructor(executor) { + function reject(value) { + assert.sameValue(value, error); + rejectCallCount += 1; + return returnValue; + } + executor(() => {throw error}, reject); +} +Constructor.resolve = function(v) { + return v; +}; +Constructor.reject = function(v) { + return v; +}; + +let pOnRejected; + +let p = { + then(onResolved, onRejected) { + pOnRejected = onRejected; + onResolved(); + } +}; + +assert.sameValue(rejectCallCount, 0, 'rejectCallCount before call to allSettled()'); + +Promise.allSettled.call(Constructor, [p]); + +assert.sameValue(rejectCallCount, 1, 'rejectCallCount after call to allSettled()'); +assert.sameValue(pOnRejected(), undefined); +assert.sameValue(rejectCallCount, 1, 'rejectCallCount after call to pOnRejected()'); +pOnRejected(); +assert.sameValue(rejectCallCount, 1, 'rejectCallCount after call to pOnRejected()'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-name.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-name.js new file mode 100644 index 0000000000..dce6efeb06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-name.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The `name` property of Promise.allSettled Reject Element functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +verifyProperty(rejectElementFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js new file mode 100644 index 0000000000..e6803c37cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: Promise.allSettled Reject Element functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new rejectElementFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-property-order.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-property-order.js new file mode 100644 index 0000000000..44a71240e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-property-order.js @@ -0,0 +1,33 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise.allSettled reject element function property order +info: | + Set order: "length", "name" +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then: function(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +var propNames = Object.getOwnPropertyNames(rejectElementFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-prototype.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-prototype.js new file mode 100644 index 0000000000..79067c1e53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-element-function-prototype.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The [[Prototype]] of Promise.allSettled Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(rejectElementFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-deferred.js new file mode 100644 index 0000000000..c249c2cfe8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-deferred.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; + +var fulfiller = { + then(resolve) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(42); + }); + } +}; +var rejector = { + then(resolve, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(simulation); + reject(); + }); + } +}; + +Promise.allSettled([fulfiller, rejector]) + .then((settleds) => { + assert.sameValue(settleds.length, 2); + assert.sameValue(settleds[0].status, 'fulfilled'); + assert.sameValue(settleds[0].value, 42); + assert.sameValue(settleds[1].status, 'fulfilled'); + assert.sameValue(settleds[1].value, simulation); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-immed.js new file mode 100644 index 0000000000..d06df2b019 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-ignored-immed.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; + +var fulfiller = { + then(resolve) { + resolve(42); + } +}; + +var lateRejector = { + then(resolve, reject) { + resolve(simulation); + reject(); + } +}; + +Promise.allSettled([fulfiller, lateRejector]) + .then((settleds) => { + assert.sameValue(settleds.length, 2); + assert.sameValue(settleds[0].status, 'fulfilled'); + assert.sameValue(settleds[0].value, 42); + assert.sameValue(settleds[1].status, 'fulfilled'); + assert.sameValue(settleds[1].value, simulation); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/reject-immed.js b/js/src/tests/test262/built-ins/Promise/allSettled/reject-immed.js new file mode 100644 index 0000000000..aa5fff5c59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/reject-immed.js @@ -0,0 +1,31 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Rejecting through immediate invocation of the provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var simulation = {}; +var thenable = { + then(_, reject) { + reject(simulation); + } +}; + +Promise.allSettled([thenable]) + .then((settleds) => { + checkSettledPromises(settleds, [{ status: 'rejected', reason: simulation }]); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js new file mode 100644 index 0000000000..d5bc9325e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js @@ -0,0 +1,85 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when Promise.allSettled resolve element function is called twice in a row. +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + onFulfilled('p2-fulfill'); + onFulfilled('p2-fulfill-unexpected'); + } +}; +var p3 = { + then(onFulfilled, onRejected) { + onFulfilled('p3-fulfill'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit.js new file mode 100644 index 0000000000..159168f2eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-before-loop-exit.js @@ -0,0 +1,81 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when two Promise.allSettled resolve element functions are called in succession. +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + p1OnFulfilled('p1-fulfill'); + onFulfilled('p2-fulfill'); + } +}; +var p3 = { + then(onFulfilled, onRejected) { + onFulfilled('p3-fulfill'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-extensible.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-extensible.js new file mode 100644 index 0000000000..0a469e3f67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-extensible.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The [[Extensible]] slot of Promise.allSettled Resolve Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert(Object.isExtensible(resolveElementFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-length.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-length.js new file mode 100644 index 0000000000..16cfbe3219 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-length.js @@ -0,0 +1,40 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The `length` property of Promise.allSettled Resolve Element functions +info: | + The length property of a Promise.allSettled resolve element function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +verifyProperty(resolveElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-name.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-name.js new file mode 100644 index 0000000000..eb6a7d1ddc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-name.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The `name` property of Promise.allSettled Resolve Element functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +verifyProperty(resolveElementFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js new file mode 100644 index 0000000000..5c1ca93aa5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: Promise.allSettled Resolve Element functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(resolveElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new resolveElementFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-property-order.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-property-order.js new file mode 100644 index 0000000000..5914500a1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-property-order.js @@ -0,0 +1,33 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise.allSettled resolve element function property order +info: | + Set order: "length", "name" +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then: function(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +var propNames = Object.getOwnPropertyNames(resolveElementFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-prototype.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-prototype.js new file mode 100644 index 0000000000..fc3a86235d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-element-function-prototype.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The [[Prototype]] of Promise.allSettled Resolve Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(resolveElementFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-from-same-thenable.js new file mode 100644 index 0000000000..f51b3406f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-from-same-thenable.js @@ -0,0 +1,91 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when Promise.allSettled resolve element function is called multiple times. +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled, p2OnFulfilled, p3OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + p2OnFulfilled = onFulfilled; + } +}; +var p3 = { + then(onFulfilled, onRejected) { + p3OnFulfilled = onFulfilled; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to allSettled()'); + +Promise.allSettled.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, 'callCount after call to allSettled()'); + +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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..1697045af9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.allSettled +info: | + Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.allSettled, arrow-function] +---*/ + +var resolver = { + then(resolve) { + new Promise((resolve) => resolve()) + .then(() => resolve(42)); + } +}; +var lateRejector = { + then(resolve, reject) { + new Promise((resolve) => resolve()) + .then(() => { + resolve(9); + reject(); + }); + } +}; + +Promise.allSettled([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution[0].value, 42); + assert.sameValue(resolution[0].status, 'fulfilled'); + assert.sameValue(resolution[1].value, 9); + assert.sameValue(resolution[1].status, 'fulfilled'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..d7847a7b6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-ignores-late-rejection.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.allSettled +info: | + Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.allSettled, arrow-function] +---*/ + +var resolver = { + then(resolve) { + resolve(42); + } +}; +var lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.allSettled([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution[0].value, 42); + assert.sameValue(resolution[0].status, 'fulfilled'); + assert.sameValue(resolution[1].value, 33); + assert.sameValue(resolution[1].status, 'fulfilled'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-callable.js new file mode 100644 index 0000000000..ebc4350938 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.allSettled ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Promise.allSettled, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.allSettled(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-thenable.js new file mode 100644 index 0000000000..389ea47977 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-non-thenable.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +esid: sec-promise.allsettled +info: | + Promise.allSettled Resolve Element Functions + + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var v1 = {}; +var v2 = {}; +var v3 = {}; + +Promise.allSettled([v1, v2, v3]) + .then(function(values) { + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: v1 + }, + { + status: 'fulfilled', + value: v2 + }, + { + status: 'fulfilled', + value: v3 + } + ], 'values'); + }, function() { + $DONE('The promise should not be rejected.'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-not-callable-reject-with-typeerror.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 0000000000..c6f9c19173 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allSettled +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + Let promiseResolve be ? Get(constructor, "resolve"). + If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + +flags: [async] +features: [Promise.allSettled, arrow-function] +---*/ + +Promise.resolve = null; + +Promise.allSettled([1]) + .then( + () => $DONE('The promise should not be resolved.'), + error => { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-poisoned-then.js new file mode 100644 index 0000000000..7d37bfa2c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-poisoned-then.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property +esid: sec-promise.allsettled +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +var value = {}; +var promise; + +try { + Object.defineProperty(Array.prototype, 'then', { + get() { + throw value; + }, + configurable: true + }); + + promise = Promise.allSettled([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the expected value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolve-thenable.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-thenable.js new file mode 100644 index 0000000000..008e9525e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolve-thenable.js @@ -0,0 +1,30 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +esid: sec-promise.allsettled +info: | + Let promiseCapability be NewPromiseCapability(C). +flags: [async] +features: [Promise.allSettled] +---*/ + +var value = {}; +var promise; + +try { + Array.prototype.then = function(resolve) { + resolve(value); + }; + + promise = Promise.allSettled([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function(val) { + assert.sameValue(val, value); +}, function() { + $DONE('The promise should not be rejected.'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-fulfilled.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-fulfilled.js new file mode 100644 index 0000000000..cfface3843 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-fulfilled.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (all fulfilled) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj = {}; +var p1 = new Promise(function(resolve) { + resolve(1); +}); +var p2 = new Promise(function(resolve) { + resolve('test262'); +}); +var p3 = new Promise(function(resolve) { + resolve(obj); +}); + +Promise.allSettled([p1, p2, p3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'fulfilled', value: 1 }, + { status: 'fulfilled', value: 'test262' }, + { status: 'fulfilled', value: obj } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-mixed.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-mixed.js new file mode 100644 index 0000000000..8a598f77a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-mixed.js @@ -0,0 +1,78 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (fulfilled and rejected) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj1 = {}; +var obj2 = {}; +var r1 = new Promise(function(_, reject) { + reject(1); +}); +var f1 = new Promise(function(resolve) { + resolve(2); +}); +var f2 = new Promise(function(resolve) { + resolve('tc39'); +}); +var r2 = new Promise(function(_, reject) { + reject('test262'); +}); +var r3 = new Promise(function(_, reject) { + reject(obj1); +}); +var f3 = new Promise(function(resolve) { + resolve(obj2); +}); + +Promise.allSettled([r1, f1, f2, r2, r3, f3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'rejected', reason: 1 }, + { status: 'fulfilled', value: 2 }, + { status: 'fulfilled', value: 'tc39' }, + { status: 'rejected', reason: 'test262' }, + { status: 'rejected', reason: obj1 }, + { status: 'fulfilled', value: obj2 } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-rejected.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-rejected.js new file mode 100644 index 0000000000..943b98c01f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-all-rejected.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (fulfiled and rejected promises) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj = {}; +var p1 = new Promise(function(_, reject) { + reject(1); +}); +var p2 = new Promise(function(_, reject) { + reject('test262'); +}); +var p3 = new Promise(function(_, reject) { + reject(obj); +}); + +Promise.allSettled([p1, p2, p3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'rejected', reason: 1 }, + { status: 'rejected', reason: 'test262' }, + { status: 'rejected', reason: obj } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-immed.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-immed.js new file mode 100644 index 0000000000..c6c2d4fcb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-immed.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled([]) returns immediately +includes: [promiseHelper.js] +flags: [async] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +Promise.allSettled([]).then(function() { + sequence.push(2); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); +}).then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); +checkSequence(sequence, 'Promises resolved in unexpected sequence'); +}).then($DONE, $DONE); + +sequence.push(1); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..e52ea2a348 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js @@ -0,0 +1,48 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve({}); +}); + +sequence.push(1); + +Promise.allSettled([p1]).then(function(resolved) { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected Promise.allSettled().then to queue second'); +}).catch($DONE); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected p1.then to queue first'); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected final then to queue last'); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-mixed.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-mixed.js new file mode 100644 index 0000000000..27bd4bcf3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-mixed.js @@ -0,0 +1,63 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(_, reject) { + reject(''); +}); +var p2 = new Promise(function(resolve) { + resolve(''); +}); +var p3 = new Promise(function(_, reject) { + reject(''); +}); + +sequence.push(1); + +p1.catch(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}); + +Promise.allSettled([p1, p2, p3]).then(function() { + sequence.push(6); + assert.sameValue(sequence.length, 6); + checkSequence(sequence, 'Expected to be called fourth.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}); + +sequence.push(2); + +p3.catch(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..959cbb40d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(_, reject) { + reject('foo'); +}); +var p2 = new Promise(function(_, reject) { + reject('bar'); +}); + +sequence.push(1); + +p1.catch(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.allSettled([p1, p2]).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.catch(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence.js new file mode 100644 index 0000000000..879d234c1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-sequence.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve(1); +}); +var p2 = new Promise(function(resolve) { + resolve(2); +}); + +sequence.push(1); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.allSettled([p1, p2]).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolved-then-catch-finally.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-then-catch-finally.js new file mode 100644 index 0000000000..15a987cb7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolved-then-catch-finally.js @@ -0,0 +1,70 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (all fulfilled) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var p0 = Promise.resolve(2).then(v => v + 1); +var p1 = Promise.reject(21).catch(v => v * 2); +var p2 = Promise.resolve('nope').then(() => { throw 'foo' }); +var p3 = Promise.reject('yes').then(() => { throw 'nope'; }); +var p4 = Promise.resolve('here').finally(() => 'nope'); +var p5 = Promise.reject('here too').finally(() => 'nope'); +var p6 = Promise.resolve('nope').finally(() => { throw 'finally'; }); +var p7 = Promise.reject('nope').finally(() => { throw 'finally after rejected'; }); +var p8 = Promise.reject(1).then(() => 'nope', () => 0); + +Promise.allSettled([p0, p1, p2, p3, p4, p5, p6, p7, p8]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'fulfilled', value: 3 }, + { status: 'fulfilled', value: 42 }, + { status: 'rejected', reason: 'foo' }, + { status: 'rejected', reason: 'yes' }, + { status: 'fulfilled', value: 'here' }, + { status: 'rejected', reason: 'here too' }, + { status: 'rejected', reason: 'finally' }, + { status: 'rejected', reason: 'finally after rejected' }, + { status: 'fulfilled', value: 0 }, + ], 'settled'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolves-empty-array.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolves-empty-array.js new file mode 100644 index 0000000000..4ca58b35a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolves-empty-array.js @@ -0,0 +1,28 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled([]) returns a Promise for an empty array +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var arg = []; + +Promise.allSettled(arg).then(function(result) { + checkSettledPromises(result, []); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/resolves-to-array.js b/js/src/tests/test262/built-ins/Promise/allSettled/resolves-to-array.js new file mode 100644 index 0000000000..27f3419b9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/resolves-to-array.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled returned a promise resolves into an array +info: | + Runtime Semantics: PerformPromiseAllSettled ( 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, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +var arg = []; + +Promise.allSettled([]).then(function(result) { + assert(Array.isArray(result)); + assert.sameValue(Object.getPrototypeOf(result), Array.prototype); + assert.notSameValue(result, arg, 'the resolved array is a new array'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/returns-promise.js b/js/src/tests/test262/built-ins/Promise/allSettled/returns-promise.js new file mode 100644 index 0000000000..4a57525a6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/returns-promise.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled returns a Promise +info: | + Promise.allSettled ( iterable ) + + 3. Let promiseCapability be ? NewPromiseCapability(C). + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). +features: [Promise.allSettled] +---*/ + +var p = Promise.allSettled([]); + +assert(p instanceof Promise); +assert.sameValue(Object.getPrototypeOf(p), Promise.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/shell.js b/js/src/tests/test262/built-ins/Promise/allSettled/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/allSettled/species-get-error.js b/js/src/tests/test262/built-ins/Promise/allSettled/species-get-error.js new file mode 100644 index 0000000000..5f2bf79d86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/allSettled/species-get-error.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled() does not retrieve `Symbol.species` property of the `this` value +esid: sec-promise.allsettled +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... +features: [Promise.allSettled, Symbol.species] +---*/ + +function C(executor) { + executor(function() {}, function() {}); +} +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error('Getter for Symbol.species called'); + } +}); + +C.resolve = function() { + throw new Test262Error(); +}; + +Promise.allSettled.call(C, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/browser.js b/js/src/tests/test262/built-ins/Promise/any/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js new file mode 100644 index 0000000000..ac713bac2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js @@ -0,0 +1,51 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: > + Cannot change result value of rejected Promise.any element after Promise.any() returned. +info: | + Promise.any Reject Element Functions + + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + +features: [Promise.any] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + executor(Test262Error.thrower, (error) => { + callCount++; + errorArray = error.errors; + }); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onFulfilled, onRejected) { + p1OnRejected = onRejected; + onRejected("onRejectedValue"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); +assert.sameValue(errorArray[0], "onRejectedValue", "errorArray after call to any()"); + +p1OnRejected("unexpectedonRejectedValue"); + +assert.sameValue(errorArray[0], "onRejectedValue", "errorArray[0] === 'onRejectedValue', after call to p1OnRejected()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js new file mode 100644 index 0000000000..bef67aa505 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: > + Cannot change result value of rejected Promise.any elements. +info: | + Promise.any Reject Element Functions + + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + +features: [Promise.any] +---*/ + +let callCount = 0; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + assert(Array.isArray(error.errors), "error.errors is array"); + assert.sameValue(error.errors.length, 2, "error.errors length"); + assert.sameValue(error.errors[0], "expectedValue-p1", "error.errors[0]"); + assert.sameValue(error.errors[1], "expectedValue-p2", "error.errors[1]"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1 = { + then(onFulfilled, onRejected) { + onRejected("expectedValue-p1"); + onRejected("unexpectedValue-p1"); + } +}; +let p2 = { + then(onFulfilled, onRejected) { + onRejected("expectedValue-p2"); + onRejected("unexpectedValue-p2"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js new file mode 100644 index 0000000000..3fae3ad0b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js @@ -0,0 +1,108 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.any ( iterable ) + + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + + GetCapabilitiesExecutor Functions + + ... + 4. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception. + 5. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception. + 6. Set promiseCapability.[[Resolve]] to resolve. + 7. Set promiseCapability.[[Reject]] to reject. + ... +features: [Promise.any] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn1.resolve = function() { + throw new Test262Error(); +}; +Promise.any.call(fn1, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with no arguments'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn2.resolve = function() { + throw new Test262Error(); +}; +Promise.any.call(fn2, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with (undefined, undefined)'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn3, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn3, []); +}, 'executor initially called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (undefined, function)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn4, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn4, []); +}, 'executor initially called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (function, undefined)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor('invalid value', 123); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn5, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn5, []); +}, 'executor initially called with (String, Number)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (String, Number)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js new file mode 100644 index 0000000000..cc3df69a44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js @@ -0,0 +1,109 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.any ( iterable ) + + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + + NewPromiseCapability ( C ) + + ... + 5. Let executor be ! CreateBuiltinFunction(steps, « [[Capability]] »). + 6. Set executor.[[Capability]] to promiseCapability. + 7. Let promise be ? Construct(C, « executor »). + 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception. + 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception. + ... +features: [Promise.any] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; +} +Object.defineProperty(fn1, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn1, []); +}, 'executor not called at all'); +assert.sameValue(checkPoint, 'a', 'executor not called at all'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; +} +Object.defineProperty(fn2, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn2, []); +}, 'executor called with no arguments'); +assert.sameValue(checkPoint, 'ab', 'executor called with no arguments'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn3, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn3, []); +}, 'executor called with (undefined, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, undefined)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; +} +Object.defineProperty(fn4, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn4, []); +}, 'executor called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, function)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn5, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn5, []); +}, 'executor called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (function, undefined)'); + +checkPoint = ''; +function fn6(executor) { + checkPoint += 'a'; + executor(123, 'invalid value'); + checkPoint += 'b'; +} +Object.defineProperty(fn6, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn6, []); +}, 'executor called with (Number, String)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (Number, String)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js new file mode 100644 index 0000000000..ce2a3074f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ +let callCount = 0; +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++ + nextCount++; + return { + done: true + }; + }, + return() { + callCount++; + returnCount++; + return {}; + } + }; + } +}; + +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + throw new Test262Error(); + }, () => { + callCount++; + reject(new Test262Error('reject throws')); + }); + }); +}; + +P.resolve = Promise.resolve; + +Promise.any.call(P, iter).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 0); + assert.sameValue(callCount, 5); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js new file mode 100644 index 0000000000..16ac4d2f0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ +let callCount = 0; +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + nextCount += 1; + return { + done: true + }; + }, + return() { + callCount++; + returnCount += 1; + return {}; + } + }; + } +}; + +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + throw new Test262Error(); + }, (...args) => { + callCount++; + reject(...args); + }); + }); +}; + +P.resolve = Promise.resolve; + +Promise.any.call(P, iter).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 0); + assert.sameValue(callCount, 5); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js new file mode 100644 index 0000000000..0022473869 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let thrown = new Test262Error(); +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + throw thrown; + }, (...args) => { + callCount++; + reject(...args); + }); + }); +}; +P.resolve = Promise.resolve; + +Promise.any.call(P, [1]) + .then(() => { + $DONE('Promise incorrectly fulfilled.'); + }, (error) => { + // The error was not the result of promise + // resolution, so will not be an AggregateError + assert.sameValue(thrown, error); + assert.sameValue(callCount, 6); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js new file mode 100644 index 0000000000..213ddb1822 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js @@ -0,0 +1,27 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a constructor value that throws an error +esid: sec-promise.any +info: | + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability + + ... + 7. Let promise be ? Construct(C, « executor »). + +features: [Promise.any] +---*/ + +function CustomPromise() { + throw new Test262Error(); +} + +assert.throws(Test262Error, function() { + Promise.any.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js new file mode 100644 index 0000000000..6331f05194 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a constructor value +esid: sec-promise.any +info: | + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + ... + 7. Return Completion(result). +features: [Promise.any, class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.any.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js new file mode 100644 index 0000000000..6901fb55e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a non-constructor value +esid: sec-promise.any +info: | + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. + +features: [Promise.any, Symbol] +---*/ + +assert.sameValue(typeof Promise.any, 'function'); + +assert.throws(TypeError, function() { + Promise.any.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js new file mode 100644 index 0000000000..1633081d7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js @@ -0,0 +1,43 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a non-object value +esid: sec-promise.any +info: | + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. + +features: [Promise.any, Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.any.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js new file mode 100644 index 0000000000..fd9d4b2d34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let error = new Test262Error(); +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + nextCount += 1; + return { + value: null, + done: false + }; + }, + return() { + returnCount += 1; + } + }; + } +}; + +Promise.resolve = function() { + throw error; +}; + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..9248d0e87e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let error = new Test262Error(); +Promise.resolve = function() { + throw error; +}; + +Promise.any([1]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (reason) => { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..175660e0c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (rejecting promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get() { + throw error; + } +}); + +Promise.any([1]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (reason) => { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js new file mode 100644 index 0000000000..976571edad --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.any ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.any(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..1db5628464 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 6. Let promiseResolve be ? Get(constructor, "resolve"). + 7. If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function, destructuring-binding] +---*/ + +let promises = [ + Promise.reject(1), + Promise.reject(1), + Promise.reject(1), +]; +let boundPromiseResolve = Promise.resolve.bind(Promise); +let getCount = 0; +let callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function(...args) { + callCount += 1; + return boundPromiseResolve(...args); + }; + } +}); + +Promise.any(promises).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, ({errors}) => { + assert.sameValue(getCount, 1); + assert.sameValue(callCount, 3); + assert.sameValue(errors.length, 3); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..28ad29b19f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 6. Let promiseResolve be ? Get(constructor, "resolve"). + 7. If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function, destructuring-binding] +---*/ + +let boundPromiseResolve = Promise.resolve.bind(Promise); +let getCount = 0; +let callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function(...args) { + callCount += 1; + return boundPromiseResolve(...args); + }; + } +}); + +Promise.any([]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, ({errors}) => { + assert.sameValue(getCount, 1); + assert.sameValue(callCount, 0); + assert.sameValue(errors.length, 0); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..5a8e758a57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..337fcbd903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let values = [1,1,1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js new file mode 100644 index 0000000000..83955852c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 2, 3]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..c4babbf46b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every iterated value'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js new file mode 100644 index 0000000000..ba5bd6be67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js @@ -0,0 +1,45 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +esid: sec-promise.any +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + PerformPromiseAny + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +features: [Promise.any] +---*/ + +let originalCallCount = 0; +let newCallCount = 0; +let P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +let originalThenable = { + then() { + originalCallCount += 1; + } +}; +let newThenable = { + then() { + newCallCount += 1; + } +}; + +Promise.any.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js new file mode 100644 index 0000000000..0fcabbf684 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js @@ -0,0 +1,32 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + assert.sameValue(args.length, 1, '`resolve` invoked with a single argument'); + assert.sameValue(this, Promise, '`this` value is the constructor'); + return boundPromiseResolve(...args); +}; + +Promise.any([1]).then(() => $DONE(), $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js new file mode 100644 index 0000000000..716430d349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, Symbol.iterator, arrow-function, computed-property-names, Symbol] +---*/ + +let error = new Test262Error(); +let promise = Promise.resolve(); +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +promise.then = function() { + throw error; +}; + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js new file mode 100644 index 0000000000..ca7ab8054c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting Promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); + +promise.then = function() { + throw error; +}; + +Promise.any([promise]).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js new file mode 100644 index 0000000000..c40020e48b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accesing the instance's `then` method (closing iterator) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, Symbol.iterator, arrow-function, computed-property-names, Symbol] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..9c42b8a7a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting Promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.any([promise]).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js new file mode 100644 index 0000000000..5b12329106 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let promises = [ + Promise.resolve(), + Promise.resolve(), + Promise.resolve(), +]; +let callCount = 0; + +promises.forEach(promise => { + let boundThen = promise.then.bind(promise); + promise.then = function(...args) { + assert.sameValue(this, promises[callCount]); + callCount += 1; + return boundThen(...args); + }; +}); + +Promise.any(promises) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then.js new file mode 100644 index 0000000000..5674ea8ecb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let promise = Promise.resolve(); +let boundThen = promise.then.bind(promise); +let callCount = 0; + +promise.then = function(resolver, rejectElement) { + assert.sameValue(this, promise); + assert.sameValue(typeof resolver, 'function'); + assert.sameValue(resolver.length, 1, 'resolver.length is 1'); + assert.sameValue(typeof rejectElement, 'function'); + assert.sameValue(rejectElement.length, 1, 'rejectElement.length is 0'); + callCount++; + return boundThen(resolver, rejectElement); +}; + +Promise.any([promise]).then(() => { + assert.sameValue(callCount, 1); + $DONE(); +}, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/is-function.js b/js/src/tests/test262/built-ins/Promise/any/is-function.js new file mode 100644 index 0000000000..4abe039b5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/is-function.js @@ -0,0 +1,12 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any is callable +features: [Promise.any] +---*/ + +assert.sameValue(typeof Promise.any, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js new file mode 100644 index 0000000000..d9f9eba172 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any([]) rejects with AggregateError, empty errors array. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + 3. Let errors be a new empty List. + ... + 8. Repeat, + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, then + i. Set iteratorRecord.[[Done]] to true. + ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let error be a newly created AggregateError object. + 2. Set error.[[AggregateErrors]] to errors. + 3. Return ThrowCompletion(error). + ... + +flags: [async] +features: [AggregateError, Promise.any, arrow-function] +---*/ + +Promise.any([]) + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(Object.getPrototypeOf(error), AggregateError.prototype); + assert(error instanceof AggregateError); + assert.sameValue(error.errors.length, 0); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js new file mode 100644 index 0000000000..0c2eeabd2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any('') rejects with AggregateError, empty errors array. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + 3. Let errors be a new empty List. + ... + 8. Repeat, + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, then + i. Set iteratorRecord.[[Done]] to true. + ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let error be a newly created AggregateError object. + 2. Set error.[[AggregateErrors]] to errors. + 3. Return ThrowCompletion(error). + ... + +features: [AggregateError, Promise.any, arrow-function] +flags: [async] +---*/ + +Promise.any('') + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(Object.getPrototypeOf(error), AggregateError.prototype); + assert(error instanceof AggregateError); + assert.sameValue(error.errors.length, 0); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js new file mode 100644 index 0000000000..b24b240e8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(new Test262Error()) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(new Test262Error()).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (error) => { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..b0f288363a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(false) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..9497e08423 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(null) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..011b1c996a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(number) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js new file mode 100644 index 0000000000..6c45a22dd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(poisoned iterable) rejects with whatever error is thrown. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + ... +features: [Promise.any, Symbol, Symbol.iterator, arrow-function] +flags: [async] +---*/ + +var poison = []; +Object.defineProperty(poison, Symbol.iterator, { + get() { + throw new Test262Error(); + } +}); + +try { + Promise.any(poison).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (error) => { + assert.sameValue(Object.getPrototypeOf(error), Test262Error.prototype); + assert(error instanceof Test262Error); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..f2009851b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any('non-empty-string') resolves with the first character in the non-empty string +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, arrow-function] +flags: [async] +---*/ + +try { + Promise.any('xyz').then(v => { + assert.sameValue(v, 'x'); + assert.sameValue(v.length, 1); + }, error => { + $DONE(`The promise should be resolved, but was rejected with error: ${error.message}`); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..563fc47b95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(Symbol()) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol] +flags: [async] +---*/ + +try { + Promise.any(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..7986819d06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(true) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..1fc2f71b7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(undefined) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js new file mode 100644 index 0000000000..3bbbea0929 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + i. Set method to ? GetMethod(obj, @@asyncIterator). + ii. If method is undefined, then + 1. Let syncMethod be ? GetMethod(obj, @@iterator). + 2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod). + ... + 4. Let iterator be ? Call(method, obj). + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js new file mode 100644 index 0000000000..f7d25a88fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js new file mode 100644 index 0000000000..f304043058 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js new file mode 100644 index 0000000000..f5444280cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: '' + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..748b8b780a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol, Symbol.iterator, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js new file mode 100644 index 0000000000..32871ce869 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..48918756b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..73bd0c5724 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js @@ -0,0 +1,64 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + + ... + + Runtime Semantics: PerformPromiseAny + + ... + Repeat + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let returnCount = 0; +let error = new Test262Error(); +let poisoned = { + done: false +}; +Object.defineProperty(poisoned, 'value', { + get() { + callCount++; + throw error; + } +}); +let iterNextValThrows = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + return poisoned; + }, + return() { + returnCount++; + return {}; + } + }; + } +}; + +Promise.any(iterNextValThrows).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert(error instanceof Test262Error); + assert.sameValue(reason, error); + assert.sameValue(callCount, 3, 'callCount === 3'); + assert.sameValue(returnCount, 0); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js new file mode 100644 index 0000000000..fe36877a63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when accessing an iterator result's `value` property (rejecting + promise) +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + + ... + + Runtime Semantics: PerformPromiseAny + + ... + Repeat + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let error = new Test262Error(); +let poisoned = { + done: false +}; +Object.defineProperty(poisoned, 'value', { + get() { + callCount++; + throw error; + } +}); +let iterNextValThrows = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + return poisoned; + } + }; + } +}; + +Promise.any(iterNextValThrows).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert(error instanceof Test262Error); + assert.sameValue(reason, error); + assert.sameValue(callCount, 3, 'callCount === 3'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js new file mode 100644 index 0000000000..19657b6ceb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return false; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js new file mode 100644 index 0000000000..de20333f61 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return null; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js new file mode 100644 index 0000000000..c6a68b81e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return 1; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js new file mode 100644 index 0000000000..645a021a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return ''; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..b581992441 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return Symbol(); + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js new file mode 100644 index 0000000000..9fe8abd861 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return true; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..9d74e6a485 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return undefined; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js new file mode 100644 index 0000000000..5dd1fd162e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js @@ -0,0 +1,61 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when advancing the provided iterable (not closing iterator) +info: | + Promise.any ( iterable ) + + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let returnCount = 0; +let poisonedDone = {}; +let error = new Test262Error(); +Object.defineProperties(poisonedDone, { + done: { + get() { + throw error; + } + }, + value: { + get() {} + } +}); +let iterStepThrows = { + [Symbol.iterator]() { + return { + next() { + return poisonedDone; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +Promise.any(iterStepThrows).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(reason, error); + assert.sameValue(returnCount, 0); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js new file mode 100644 index 0000000000..7f3fbe4ad9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when advancing the provided iterable (rejecting promise) +info: | + Promise.any ( iterable ) + + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let poisonedDone = {}; +let error = new Test262Error(); +Object.defineProperties(poisonedDone, { + done: { + get() { + throw error; + } + }, + value: { + get() { + $DONE('The `value` property should not be accessed.'); + } + } +}); +let iterStepThrows = { + [Symbol.iterator]() { + return { + next() { + return poisonedDone; + } + }; + } +}; + +Promise.any(iterStepThrows).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/length.js b/js/src/tests/test262/built-ins/Promise/any/length.js new file mode 100644 index 0000000000..85316c7bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any `length` property +info: | + ES Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise.any, 'length', { + configurable: true, + writable: false, + enumerable: false, + value: 1, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/name.js b/js/src/tests/test262/built-ins/Promise/any/name.js new file mode 100644 index 0000000000..f55f11b358 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/name.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any `name` property +info: | + ES Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise.any, 'name', { + configurable: true, + writable: false, + enumerable: false, + value: 'any', +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js b/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js new file mode 100644 index 0000000000..e99d027281 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseany +description: > + Each Promise.any element is called with a new Promise.any Reject Element function. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + k. Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + ... + +features: [Promise.any] +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(rejectFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0; +var callCount2 = 0; +var p1OnRejected; + +var p1 = { + then(_, onRejected) { + callCount1 += 1; + p1OnRejected = onRejected; + assert.notSameValue(onRejected, rejectFunction, 'p1.then'); + } +}; +var p2 = { + then(_, onRejected) { + callCount2 += 1; + assert.notSameValue(onRejected, rejectFunction, 'p2.then'); + assert.notSameValue(onRejected, p1OnRejected, 'p1.onRejected != p2.onRejected'); + } +}; + +Promise.any.call(Constructor, [p1, p2]); +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js new file mode 100644 index 0000000000..94e37ef3ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.any does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Promise.any, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.any), false, 'isConstructor(Promise.any) must return false'); + +assert.throws(TypeError, () => { + new Promise.any([1]); +}, '`new Promise.any([1])` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/prop-desc.js b/js/src/tests/test262/built-ins/Promise/any/prop-desc.js new file mode 100644 index 0000000000..89af2db227 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/prop-desc.js @@ -0,0 +1,23 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any property descriptor +info: | + ES Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise, 'any', { + configurable: true, + writable: true, + enumerable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js b/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js new file mode 100644 index 0000000000..0a4da17aa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any rejection reasons from various rejections are all present +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let rejections = [ + Promise.reject('a'), + new Promise((_, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.resolve(Promise.reject('d')), +]; + +Promise.any(rejections) + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(error.errors.length, rejections.length); + assert.sameValue(error.errors.join(''), 'abcd'); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js new file mode 100644 index 0000000000..66206ac8f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js @@ -0,0 +1,32 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: Rejecting through deferred invocation of the provided resolving function +info: | + ... + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + ... + + +flags: [async] +features: [AggregateError, Promise.any, arrow-function] +---*/ + +var rejection = {}; +var thenable = { + then(_, reject) { + new Promise((resolve) => resolve()) + .then(() => reject(rejection)); + } +}; + +Promise.any([thenable]) + .then(() => { + $DONE('The promise should be rejected.'); + }, (aggregate) => { + assert(aggregate instanceof AggregateError); + assert.sameValue(aggregate.errors.length, 1); + assert.sameValue(aggregate.errors[0], rejection); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js new file mode 100644 index 0000000000..806e937f37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The [[Extensible]] slot of Promise.any Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert(Object.isExtensible(rejectElementFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js new file mode 100644 index 0000000000..dce2b491c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The `length` property of Promise.any Reject Element functions +info: | + The length property of a Promise.any Reject Element function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(rejectElementFunction.length, 1); + +verifyProperty(rejectElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js new file mode 100644 index 0000000000..e7b71509e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The `name` property of Promise.any Reject Element functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +verifyProperty(rejectElementFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js new file mode 100644 index 0000000000..c11012de84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: Promise.any Reject Element functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new rejectElementFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-property-order.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-property-order.js new file mode 100644 index 0000000000..a463bde468 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-property-order.js @@ -0,0 +1,33 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise.any resolve element function property order +info: | + Set order: "length", "name" +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then: function(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +var propNames = Object.getOwnPropertyNames(rejectElementFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js new file mode 100644 index 0000000000..a6b147ec0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The [[Prototype]] of Promise.any Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(rejectElementFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js new file mode 100644 index 0000000000..9c55285599 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js @@ -0,0 +1,70 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting with a non-thenable object value +esid: sec-promise.any +info: | + PerformPromiseAny + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + + Promise.any Reject Element Functions + + Let alreadyCalled be F.[[AlreadyCalled]]. + If alreadyCalled.[[Value]] is true, return undefined. + Set alreadyCalled.[[Value]] to true. + ... +features: [Promise.any] +---*/ + +let callCount = 0; +let error; + +function Constructor(executor) { + function reject(result) { + callCount += 1; + error = result; + } + executor(() => {throw new Test262Error()}, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected, p2OnRejected, p3OnRejected; + +let p1 = { + then(_, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(_, onRejected) { + p2OnRejected = onRejected; + } +}; +let p3 = { + then(_, onRejected) { + p3OnRejected = onRejected; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to any()'); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, 'callCount after call to any()'); + +p1OnRejected('p1-rejection'); +p1OnRejected('p1-rejection-unexpected-1'); +p1OnRejected('p1-rejection-unexpected-2'); + +assert.sameValue(callCount, 0, 'callCount after resolving p1'); + +p2OnRejected('p2-rejection'); +p3OnRejected('p3-rejection'); + +assert.sameValue(callCount, 1, 'callCount after resolving all elements'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js new file mode 100644 index 0000000000..4e98e1ab01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let fulfiller = { + then(resolve) { + new Promise((resolve) => { + callCount++; + resolve(); + }) + .then(() => { + callCount++; + resolve(); + }); + } +}; +let rejector = { + then(resolve, reject) { + new Promise((resolve) => { + callCount++; + resolve(); + }) + .then(() => { + callCount++; + resolve(); + reject(); + }); + } +}; + +Promise.all([fulfiller, rejector]) + .then(() => { + assert.sameValue(callCount, 4, "callCount === 4"); + $DONE(); + }, () => { + $DONE("The promise should not be rejected."); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js new file mode 100644 index 0000000000..11b6976871 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfiller = { + then(resolve) { + resolve(); + } +}; +let lateRejector = { + then(resolve, reject) { + resolve(); + reject(); + } +}; + +Promise.any([fulfiller, lateRejector]) + .then(() => { + $DONE(); + }, () => { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-immed.js b/js/src/tests/test262/built-ins/Promise/any/reject-immed.js new file mode 100644 index 0000000000..33d445e1de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-immed.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: Rejecting through immediate invocation of the provided resolving function +info: | + ... + Let promiseCapability be NewPromiseCapability(C). + ... + Let result be PerformPromiseAny(iteratorRecord, promiseCapability, C). + ... + + Runtime Semantics: PerformPromiseAny + ... + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", + « resultCapability.[[Resolve]], rejectElement »). + + + Promise.any Reject Element Functions + ... + 6. Return RejectPromise(promise, reason). +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let thenable = { + then(_, reject) { + callCount++; + reject('reason'); + } +}; + +Promise.any([thenable]) + .then(() => { + $DONE('The promise should not be fulfilled.'); + }, (error) => { + assert.sameValue(callCount, 1, "callCount === 1"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + assert.sameValue(error.errors[0], "reason", "error.errors[0] === 'reason'"); + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js new file mode 100644 index 0000000000..19e2e3779e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js @@ -0,0 +1,101 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Cannot tamper remainingElementsCount when Promise.all resolve element function is called twice in a row. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + errorArray = error.errors; + + assert(Array.isArray(error.errors), "error is array"); + assert.sameValue(error.errors.length, 3, "error.length"); + assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'"); + assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'"); + assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onResolved, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(onResolved, onRejected) { + onRejected("p2-rejection"); + onRejected("unexpectedonRejectedValue"); + } +}; +let p3 = { + then(onResolved, onRejected) { + onRejected("p3-rejection"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, "callCount after call to any()"); + +p1OnRejected("p1-rejection"); + +assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()"); +assert.sameValue( + errorArray[0], + "p1-rejection", + "errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[1], + "p2-rejection", + "errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[2], + "p3-rejection", + "errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)" +); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js new file mode 100644 index 0000000000..07daaa55dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js @@ -0,0 +1,102 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Cannot tamper remainingElementsCount when two Promise.any Reject Element Function are called in succession. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + errorArray = error.errors; + + assert(Array.isArray(error.errors), "error is array"); + assert.sameValue(error.errors.length, 3, "error.length"); + assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'"); + assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'"); + assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onResolved, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(onResolved, onRejected) { + p1OnRejected("p1-rejection"); + onRejected("p2-rejection"); + } +}; +let p3 = { + then(onResolved, onRejected) { + onRejected("p3-rejection"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); +assert.sameValue(errorArray[0], "p1-rejection", "errorArray[0] === 'p1-rejection'"); +assert.sameValue(errorArray[1], "p2-rejection", "errorArray[1] === 'p2-rejection'"); +assert.sameValue(errorArray[2], "p3-rejection", "errorArray[2] === 'p3-rejection'"); + +p1OnRejected("unexpectedonRejectedValue"); + +assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()"); +assert.sameValue( + errorArray[0], + "p1-rejection", + "errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[1], + "p2-rejection", + "errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[2], + "p3-rejection", + "errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js new file mode 100644 index 0000000000..6aee6c9155 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js @@ -0,0 +1,23 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any resolves with the first item that does not reject. +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfillables = [ + Promise.reject('a'), + new Promise((resolve, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.reject('d').catch(v => v), +]; + +Promise.any(fulfillables) + .then((resolution) => { + assert.sameValue(resolution, 'd'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js new file mode 100644 index 0000000000..e5c6534b03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js @@ -0,0 +1,23 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any resolves with the first item that does not reject. +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfillables = [ + Promise.reject('a'), + new Promise((resolve, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.resolve(Promise.reject('d').catch(v => v)), +]; + +Promise.any(fulfillables) + .then((resolution) => { + assert.sameValue(resolution, 'd'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js new file mode 100644 index 0000000000..3066d969ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js @@ -0,0 +1,46 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseany +description: > + Promise.any does not prevent resolve from being called multiple times. +features: [Promise.any, arrow-function] +includes: [promiseHelper.js] +---*/ +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function resolve(value) { + callCount += 1; + sequence.push(value); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +let pResolve; +let a = { + then(resolver, rejector) { + pResolve = resolver; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to any()'); + +Promise.any.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to any()'); + +pResolve(1); +pResolve(2); +pResolve(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..89339379fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +var resolver = { + then(resolve) { + new Promise((resolve) => resolve()) + .then(() => resolve(42)); + } +}; +var lateRejector = { + then(resolve, reject) { + new Promise((resolve) => resolve()) + .then(() => { + resolve(9); + reject(); + }); + } +}; + +Promise.any([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..446a12191f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +var resolver = { + then(resolve) { + resolve(42); + } +}; +var lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.any([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js new file mode 100644 index 0000000000..4baf72bb66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.any ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.any(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js new file mode 100644 index 0000000000..e7fb6b4417 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js @@ -0,0 +1,26 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +esid: sec-promise.any +info: | + PerformPromiseAny + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any] +---*/ + +const a = {}; +const b = {}; +const c = {}; + +Promise.any([a, b, c]) + .then((value) => { + assert.sameValue(value, a); + }, () => { + $DONE('The promise should not be rejected.'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js b/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 0000000000..6623f8c160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + Let promiseResolve be ? Get(constructor, "resolve"). + If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +Promise.resolve = null; + +Promise.any([1]) + .then( + () => $DONE('The promise should not be resolved.'), + error => { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..fcb54a8457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise(resolve => { + resolve({}); +}); + +sequence.push(1); + +Promise.any([p1]).then((resolved) => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected Promise.any().then to queue second'); +}).catch($DONE); + +p1.then(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected p1.then to queue first'); +}).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected final then to queue last'); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js new file mode 100644 index 0000000000..b993f5776b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js @@ -0,0 +1,70 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise((_, reject) => { + reject(''); +}); +let p2 = new Promise(resolve => { + resolve(''); +}); +let p3 = new Promise((_, reject) => { + reject(''); +}); + +sequence.push(1); + +p1.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2, p3]).then(() => { + sequence.push(6); + assert.sameValue(sequence.length, 6); + checkSequence(sequence, 'Expected to be called fourth.'); +}).then($DONE, $DONE); + +p2.then(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); + +p3.catch(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).catch($DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..5562617df6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise((_, reject) => { + reject('foo'); +}); +let p2 = new Promise((_, reject) => { + reject('bar'); +}); + +sequence.push(1); + +p1.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2]).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, outcome => { + assert(outcome instanceof AggregateError); + assert.sameValue(outcome.errors.length, 2); + assert.sameValue(outcome.errors[0], 'foo'); + assert.sameValue(outcome.errors[1], 'bar'); +}).then($DONE, $DONE); + +p2.catch(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js new file mode 100644 index 0000000000..75be407c35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + 6.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + Return ThrowCompletion(error). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +var sequence = []; + +var p1 = new Promise(resolve => { + resolve(1); +}); +var p2 = new Promise(resolve => { + resolve(2); +}); + +sequence.push(1); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); +checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2]).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/returns-promise.js b/js/src/tests/test262/built-ins/Promise/any/returns-promise.js new file mode 100644 index 0000000000..cbcd937b63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/returns-promise.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any returns a Promise +info: | + Promise.any ( iterable ) + + 2. Let promiseCapability be ? NewPromiseCapability(C). + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 7. Return Completion(result). +features: [Promise.any] +---*/ + +var p = Promise.any([]); + +assert(p instanceof Promise); +assert.sameValue(Object.getPrototypeOf(p), Promise.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/shell.js b/js/src/tests/test262/built-ins/Promise/any/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/any/species-get-error.js b/js/src/tests/test262/built-ins/Promise/any/species-get-error.js new file mode 100644 index 0000000000..24ce52bd69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/species-get-error.js @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any() does not access a `Symbol.species` property of the `this` value +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + ... + +features: [Promise.any, Symbol.species] +---*/ +function C(executor) { + executor(() => {}, () => {}); +} + +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error("Getter for Symbol.species called"); + } +}); + +C.resolve = function() { + throw new Test262Error("C.resolve called unexpectedly"); +}; + +Promise.any.call(C, [1]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/browser.js b/js/src/tests/test262/built-ins/Promise/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/constructor.js b/js/src/tests/test262/built-ins/Promise/constructor.js new file mode 100644 index 0000000000..79e15dab44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/constructor.js @@ -0,0 +1,11 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +description: > + The Promise constructor is a built-in function +---*/ + +assert.sameValue(typeof Promise, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/create-resolving-functions-reject.js b/js/src/tests/test262/built-ins/Promise/create-resolving-functions-reject.js new file mode 100644 index 0000000000..05297b7993 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/create-resolving-functions-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createresolvingfunctions +description: > + reject is anonymous built-in function with length of 1. +info: | + CreateResolvingFunctions ( promise ) + + ... + 7. Let reject be ! CreateBuiltinFunction(stepsReject, « [[Promise]], [[AlreadyResolved]] »). +features: [Reflect.construct, arrow-function] +includes: [isConstructor.js] +flags: [async] +---*/ + +Promise.resolve(1).then(function() { + return Promise.resolve(); +}).then($DONE, $DONE); + +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve, reject) { + assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false'); + assert.throws(TypeError, () => { + new reject(); + }, '`new reject()` throws TypeError'); + + assert.sameValue(reject.length, 1, 'The value of reject.length is 1'); + assert.sameValue(reject.name, '', 'The value of reject.name is ""'); + + return then.call(this, resolve, reject); +}; diff --git a/js/src/tests/test262/built-ins/Promise/create-resolving-functions-resolve.js b/js/src/tests/test262/built-ins/Promise/create-resolving-functions-resolve.js new file mode 100644 index 0000000000..c2c4dc60d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/create-resolving-functions-resolve.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createresolvingfunctions +description: > + resolve is anonymous built-in function with length of 1. +info: | + CreateResolvingFunctions ( promise ) + + ... + 3. Let resolve be ! CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »). +features: [Reflect.construct, arrow-function] +includes: [isConstructor.js] +flags: [async] +---*/ + +Promise.resolve(1).then(function() { + return Promise.resolve(); +}).then($DONE, $DONE); + +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve, reject) { + assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false'); + assert.throws(TypeError, () => { + new resolve(); + }, '`new resolve()` throws TypeError'); + + assert.sameValue(resolve.length, 1, 'The value of resolve.length is 1'); + assert.sameValue(resolve.name, '', 'The value of resolve.name is ""'); + + return then.call(this, resolve, reject); +}; diff --git a/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-executor.js b/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-executor.js new file mode 100644 index 0000000000..a33d887ca6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-executor.js @@ -0,0 +1,33 @@ +// |reftest| async +// 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). + ... +flags: [async] +---*/ + +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/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-thenable-job.js b/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-thenable-job.js new file mode 100644 index 0000000000..b1ca3168de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/exception-after-resolve-in-thenable-job.js @@ -0,0 +1,38 @@ +// |reftest| async +// 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). + ... +flags: [async] +---*/ + +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/js/src/tests/test262/built-ins/Promise/exec-args.js b/js/src/tests/test262/built-ins/Promise/exec-args.js new file mode 100644 index 0000000000..a2b23f1137 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/exec-args.js @@ -0,0 +1,35 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.3.1 +description: Promise executor is invoked synchronously +info: | + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + + The length property of a promise resolve function is 1. + + 25.4.1.3.1 Promise Reject Functions + + The length property of a promise reject function is 1. +---*/ + +var callCount = 0; +var resolve, reject, argCount; + +new Promise(function(a, b) { + resolve = a; + reject = b; + argCount = arguments.length; +}); + +assert.sameValue(typeof resolve, 'function', 'type of first argument'); +assert.sameValue(resolve.length, 1, 'length of first argument'); +assert.sameValue(typeof reject, 'function', 'type of second argument'); +assert.sameValue(reject.length, 1, 'length of second argument'); +assert.sameValue(argCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-call-context-sloppy.js b/js/src/tests/test262/built-ins/Promise/executor-call-context-sloppy.js new file mode 100644 index 0000000000..6151199642 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-call-context-sloppy.js @@ -0,0 +1,24 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +author: Sam Mikes +description: > + Promise executor is called in global object context in sloppy mode. +info: | + 25.6.3.1 Promise ( executor ) + + [...] + 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »). +flags: [noStrict] +---*/ + +var _this; + +new Promise(function() { + _this = this; +}); + +assert.sameValue(_this, this); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-call-context-strict-strict.js b/js/src/tests/test262/built-ins/Promise/executor-call-context-strict-strict.js new file mode 100644 index 0000000000..e6eec27aac --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-call-context-strict-strict.js @@ -0,0 +1,25 @@ +'use strict'; +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +author: Sam Mikes +description: > + Promise executor is called in `undefined` context in strict mode. +info: | + 25.6.3.1 Promise ( executor ) + + [...] + 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »). +flags: [onlyStrict] +---*/ + +var _this; + +new Promise(function() { + _this = this; +}); + +assert.sameValue(_this, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-extensible.js b/js/src/tests/test262/built-ins/Promise/executor-function-extensible.js new file mode 100644 index 0000000000..901795ecac --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-extensible.js @@ -0,0 +1,23 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.5.1 +description: The [[Extensible]] slot of GetCapabilitiesExecutor functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +assert(Object.isExtensible(executorFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-length.js b/js/src/tests/test262/built-ins/Promise/executor-function-length.js new file mode 100644 index 0000000000..1aa7f25e45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-length.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.1.5.1 +description: The `length` property of GetCapabilitiesExecutor functions +info: | + The length property of a GetCapabilitiesExecutor function is 2. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +assert.sameValue(executorFunction.length, 2); + +verifyNotEnumerable(executorFunction, "length"); +verifyNotWritable(executorFunction, "length"); +verifyConfigurable(executorFunction, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-name.js b/js/src/tests/test262/built-ins/Promise/executor-function-name.js new file mode 100644 index 0000000000..dc38f24ef4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-name.js @@ -0,0 +1,33 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-getcapabilitiesexecutor-functions +description: The `name` property of GetCapabilitiesExecutor functions +info: | + A GetCapabilitiesExecutor function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +verifyProperty(executorFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/executor-function-not-a-constructor.js new file mode 100644 index 0000000000..5e1f360112 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-not-a-constructor.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. + +/*--- +esid: sec-getcapabilitiesexecutor-functions +description: GetCapabilitiesExecutor function is not constructor +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +assert.sameValue( + Object.prototype.hasOwnProperty.call(executorFunction, "prototype"), + false, + 'Object.prototype.hasOwnProperty.call(executorFunction, "prototype") must return false' +); +assert.sameValue(isConstructor(executorFunction), false, 'isConstructor(executorFunction) must return false'); + +assert.throws(TypeError, () => { + new executorFunction(); +}, '`new executorFunction()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-property-order.js b/js/src/tests/test262/built-ins/Promise/executor-function-property-order.js new file mode 100644 index 0000000000..207dd3b6f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-property-order.js @@ -0,0 +1,25 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise executor function property order +info: | + Set order: "length", "name" +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +var propNames = Object.getOwnPropertyNames(executorFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-function-prototype.js b/js/src/tests/test262/built-ins/Promise/executor-function-prototype.js new file mode 100644 index 0000000000..e01753b9e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-function-prototype.js @@ -0,0 +1,25 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.5.1 +description: The [[Prototype]] of GetCapabilitiesExecutor functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +---*/ + +var executorFunction; + +function NotPromise(executor) { + executorFunction = executor; + executor(function() {}, function() {}); +} +Promise.resolve.call(NotPromise); + +assert.sameValue(Object.getPrototypeOf(executorFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/executor-not-callable.js new file mode 100644 index 0000000000..76478606f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/executor-not-callable.js @@ -0,0 +1,31 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +author: Sam Mikes +description: > + Promise constructor throws TypeError if executor is not callable. +info: | + 25.6.3.1 Promise ( executor ) + + [...] + 2. If IsCallable(executor) is false, throw a TypeError exception. +---*/ + +assert.throws(TypeError, function() { + new Promise('not callable'); +}); + +assert.throws(TypeError, function() { + new Promise(1); +}); + +assert.throws(TypeError, function() { + new Promise(null); +}); + +assert.throws(TypeError, function() { + new Promise({}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt-executor-not-callable.js new file mode 100644 index 0000000000..5a31248bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt-executor-not-callable.js @@ -0,0 +1,37 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +description: > + Promise constructor gets prototype after checking that executor is callable. +info: | + 25.6.3.1 Promise ( executor ) + + [...] + 2. If IsCallable(executor) is false, throw a TypeError exception. + 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »). + + 9.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + [...] + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + + 9.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + [...] + 3. Let proto be ? Get(constructor, "prototype"). +features: [Reflect, Reflect.construct] +---*/ + +var bound = (function() {}).bind(); +Object.defineProperty(bound, 'prototype', { + get: function() { + throw new Test262Error(); + }, +}); + +assert.throws(TypeError, function() { + Reflect.construct(Promise, [], bound); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt.js b/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt.js new file mode 100644 index 0000000000..5cbf716e9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/get-prototype-abrupt.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +description: > + Abrupt completion from "prototype" property access +info: | + 25.6.3.1 Promise ( executor ) + + [...] + 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »). + + 9.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + [...] + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + + 9.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + [...] + 3. Let proto be ? Get(constructor, "prototype"). +features: [Reflect, Reflect.construct] +---*/ + +var bound = (function() {}).bind(); +Object.defineProperty(bound, 'prototype', { + get: function() { + throw new Test262Error(); + }, +}); + +assert.throws(Test262Error, function() { + Reflect.construct(Promise, [function() {}], bound); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/is-a-constructor.js b/js/src/tests/test262/built-ins/Promise/is-a-constructor.js new file mode 100644 index 0000000000..4b6dbe371e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/is-a-constructor.js @@ -0,0 +1,26 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + The Promise constructor implements [[Construct]] +info: | + IsConstructor ( argument ) + + The abstract operation IsConstructor takes argument argument (an ECMAScript language value). + It determines if argument is a function object with a [[Construct]] internal method. + It performs the following steps when called: + + If Type(argument) is not Object, return false. + If argument has a [[Construct]] internal method, return true. + Return false. +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise), true, 'isConstructor(Promise) must return true'); +new Promise(() => {}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/length.js b/js/src/tests/test262/built-ins/Promise/length.js new file mode 100644 index 0000000000..52923a039c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.3.1 +description: Promise `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.length, 1); + +verifyNotEnumerable(Promise, 'length'); +verifyNotWritable(Promise, 'length'); +verifyConfigurable(Promise, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/name.js b/js/src/tests/test262/built-ins/Promise/name.js new file mode 100644 index 0000000000..715bc448f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.3.1 +description: Promise `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.name, 'Promise'); + +verifyNotEnumerable(Promise, 'name'); +verifyNotWritable(Promise, 'name'); +verifyConfigurable(Promise, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/promise.js b/js/src/tests/test262/built-ins/Promise/promise.js new file mode 100644 index 0000000000..5c8ce7ac4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/promise.js @@ -0,0 +1,27 @@ +// Copyright 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-constructor +description: > + Property descriptor of Promise +info: | + 25.6.3 The Promise Constructor + + * is the initial value of the Promise property of the global object. + + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyProperty(this, 'Promise', { + value: Promise, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/property-order.js b/js/src/tests/test262/built-ins/Promise/property-order.js new file mode 100644 index 0000000000..7f156d9196 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/property-order.js @@ -0,0 +1,17 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise constructor property order +info: | + Set order: "length", "name", ... +---*/ + +var propNames = Object.getOwnPropertyNames(Promise); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/Promise/proto-from-ctor-realm.js new file mode 100644 index 0000000000..8cba0cff9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/proto-from-ctor-realm.js @@ -0,0 +1,33 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +description: Default [[Prototype]] value derived from realm of the newTarget +info: | + [...] + 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, + "%PromisePrototype%", « [[PromiseState]], [[PromiseResult]], + [[PromiseFulfillReactions]], [[PromiseRejectReactions]], + [[PromiseIsHandled]] »). + [...] + + 9.1.14 GetPrototypeFromConstructor + + [...] + 3. Let proto be ? Get(constructor, "prototype"). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Let proto be realm's intrinsic object named intrinsicDefaultProto. + [...] +features: [cross-realm, Reflect] +---*/ + +var other = $262.createRealm().global; +var C = new other.Function(); +C.prototype = null; + +var o = Reflect.construct(Promise, [function() {}], C); + +assert.sameValue(Object.getPrototypeOf(o), other.Promise.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js new file mode 100644 index 0000000000..3c08a74243 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js @@ -0,0 +1,18 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise prototype object exists, is object, not enumerable, writable, + or configurable +es6id: S25.4.4.2_A1.1_T1 +author: Sam Mikes +description: Promise prototype exists +---*/ +assert.notSameValue( + Promise.prototype, + undefined, + 'The value of Promise.prototype is expected to not equal ``undefined``' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js new file mode 100644 index 0000000000..5095976ce7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js @@ -0,0 +1,17 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.constructor is the Promise constructor +es6id: S25.4.5_A3.1_T1 +author: Sam Mikes +description: Promise.prototype.constructor is the Promise constructor +---*/ +assert.sameValue( + Promise.prototype.constructor, + Promise, + 'The value of Promise.prototype.constructor is expected to equal the value of Promise' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js new file mode 100644 index 0000000000..0d7d71d804 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js @@ -0,0 +1,23 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.4 +description: > + `Symbol.toStringTag` property descriptor +info: | + The initial value of the @@toStringTag property is the String value + "Promise". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(Promise.prototype[Symbol.toStringTag], 'Promise'); + +verifyNotEnumerable(Promise.prototype, Symbol.toStringTag); +verifyNotWritable(Promise.prototype, Symbol.toStringTag); +verifyConfigurable(Promise.prototype, Symbol.toStringTag); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js new file mode 100644 index 0000000000..0f145ac2b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js @@ -0,0 +1,16 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise prototype.catch is a function +es6id: S25.4.5.1_A1.1_T1 +author: Sam Mikes +description: Promise.prototype.catch is a function +---*/ +assert( + !!(Promise.prototype.catch instanceof Function), + 'The value of !!(Promise.prototype.catch instanceof Function) is expected to be true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js new file mode 100644 index 0000000000..efdf80c4a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js @@ -0,0 +1,19 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + catch is a method on a Promise +es6id: S25.4.5.1_A2.1_T1 +author: Sam Mikes +description: catch is a method on a Promise +---*/ + +var p = Promise.resolve(3); + +assert( + !!(p.catch instanceof Function), + 'The value of !!(p.catch instanceof Function) is expected to be true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js new file mode 100644 index 0000000000..415daf47ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + catch(arg) is equivalent to then(undefined, arg) +es6id: S25.4.5.1_A3.1_T1 +author: Sam Mikes +description: catch is implemented in terms of then +flags: [async] +---*/ + +var arg = {}; + +var p = Promise.resolve(arg); + +p.catch(function() { + throw new Test262Error("Should not be called - promise is fulfilled"); +}).then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js new file mode 100644 index 0000000000..df555fd774 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + catch(arg) is equivalent to then(undefined, arg) +es6id: S25.4.5.1_A3.1_T2 +author: Sam Mikes +description: catch is implemented in terms of then +flags: [async] +---*/ + +var arg = {}; + +var p = Promise.reject(arg); + +p.then(function() { + throw new Test262Error("Should not be called: did not expect promise to be fulfilled"); +}).catch(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js new file mode 100644 index 0000000000..e02959e8db --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js @@ -0,0 +1,54 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: Promise.prototype.catch invokes `then` method +info: | + 1. Let promise be the this value. + 2. Return Invoke(promise, "then", «undefined, onRejected»). +---*/ + +var target = {}; +var returnValue = {}; +var callCount = 0; +var thisValue = null; +var argCount = null; +var firstArg = null; +var secondArg = null; +var result = null; + +target.then = function(a, b) { + callCount += 1; + + thisValue = this; + argCount = arguments.length; + firstArg = a; + secondArg = b; + + return returnValue; +}; + +result = Promise.prototype.catch.call(target, 1, 2, 3); + +assert.sameValue(callCount, 1, 'Invokes `then` method exactly once'); +assert.sameValue( + thisValue, + target, + 'Invokes `then` method with the instance as the `this` value' +); +assert.sameValue( + argCount, 2, 'Invokes `then` method with exactly two single arguments' +); +assert.sameValue( + firstArg, + undefined, + 'Invokes `then` method with `undefined` as the first argument' +); +assert.sameValue( + secondArg, 1, 'Invokes `then` method with the provided argument' +); +assert.sameValue( + result, returnValue, 'Returns the result of the invocation of `then`' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js new file mode 100644 index 0000000000..1b487e62d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: Promise.prototype.catch `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.prototype.catch.length, 1); + +verifyNotEnumerable(Promise.prototype.catch, 'length'); +verifyNotWritable(Promise.prototype.catch, 'length'); +verifyConfigurable(Promise.prototype.catch, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js new file mode 100644 index 0000000000..25a93a3bb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: Promise.prototype.catch `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.prototype.catch.name, 'catch'); + +verifyNotEnumerable(Promise.prototype.catch, 'name'); +verifyNotWritable(Promise.prototype.catch, 'name'); +verifyConfigurable(Promise.prototype.catch, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js new file mode 100644 index 0000000000..2ff5558742 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.prototype.catch does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue( + isConstructor(Promise.prototype.catch), + false, + 'isConstructor(Promise.prototype.catch) must return false' +); + +assert.throws(TypeError, () => { + let p = new Promise(() => {}); new p.catch(); +}, '`let p = new Promise(() => {}); new p.catch()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js new file mode 100644 index 0000000000..2866aaa2d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: Promise.prototype.catch property descriptor +info: | + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(typeof Promise.prototype.catch, 'function'); + +verifyNotEnumerable(Promise.prototype, 'catch'); +verifyWritable(Promise.prototype, 'catch'); +verifyConfigurable(Promise.prototype, 'catch'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js new file mode 100644 index 0000000000..888c8b39f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.catch +description: > + Promise.prototype.catch called with a non-object-coercible `this` value +info: | + 1. Let promise be the this value. + 2. Return ? Invoke(promise, "then", «undefined, onRejected»). + + 7.3.18 Invoke + + 1. Assert: IsPropertyKey(P) is true. + 2. If argumentsList was not passed, let argumentsList be a new empty List. + 3. Let func be ? GetV(V, P). + 4. Return ? Call(func, V, argumentsList). + + 7.3.2 GetV + + 1. Assert: IsPropertyKey(P) is true. + 2. Let O be ? ToObject(V). +---*/ + +assert.throws(TypeError, function() { + Promise.prototype.catch.call(undefined); +}, 'undefined'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call(null); +}, 'null'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js new file mode 100644 index 0000000000..4f71abec7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.catch +description: > + Promise.prototype.catch called with an object-coercible `this` value +info: | + 1. Let promise be the this value. + 2. Return ? Invoke(promise, "then", «undefined, onRejected»). + + 7.3.18 Invoke + + 1. Assert: IsPropertyKey(P) is true. + 2. If argumentsList was not passed, let argumentsList be a new empty List. + 3. Let func be ? GetV(V, P). + 4. Return ? Call(func, V, argumentsList). + + 7.3.2 GetV + + 1. Assert: IsPropertyKey(P) is true. + 2. Let O be ? ToObject(V). +features: [Symbol] +---*/ + +var booleanCount = 0; +Boolean.prototype.then = function() { + booleanCount += 1; +}; +Promise.prototype.catch.call(true); +assert.sameValue(booleanCount, 1, 'boolean'); + +var numberCount = 0; +Number.prototype.then = function() { + numberCount += 1; +}; +Promise.prototype.catch.call(34); +assert.sameValue(numberCount, 1, 'number'); + +var stringCount = 0; +String.prototype.then = function() { + stringCount += 1; +}; +Promise.prototype.catch.call(''); +assert.sameValue(stringCount, 1, 'string'); + +var symbolCount = 0; +Symbol.prototype.then = function() { + symbolCount += 1; +}; +Promise.prototype.catch.call(Symbol()); +assert.sameValue(symbolCount, 1, 'symbol'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js new file mode 100644 index 0000000000..861f78bd9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js @@ -0,0 +1,75 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.catch +description: > + Promise.prototype.catch called with a `this` value that does not define a + callable `this` property +info: | + 1. Let promise be the this value. + 2. Return ? Invoke(promise, "then", «undefined, onRejected»). + + 7.3.18 Invoke + + 1. Assert: IsPropertyKey(P) is true. + 2. If argumentsList was not passed, let argumentsList be a new empty List. + 3. Let func be ? GetV(V, P). + 4. Return ? Call(func, V, argumentsList). + + 7.3.2 GetV + + 1. Assert: IsPropertyKey(P) is true. + 2. Let O be ? ToObject(V). + 3. Return ? O.[[Get]](P, V). + + 7.3.12 Call (F, V [ , argumentsList ]) + + 1. If argumentsList was not passed, let argumentsList be a new empty List. + 2. If IsCallable(F) is false, throw a TypeError exception. + 3. Return ? F.[[Call]](V, argumentsList). +features: [Symbol] +---*/ + +var symbol = Symbol(); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({}); +}, 'undefined'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: null + }); +}, 'null'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: 1 + }); +}, 'number'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: '' + }); +}, 'string'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: true + }); +}, 'boolean'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: symbol + }); +}, 'symbol'); + +assert.throws(TypeError, function() { + Promise.prototype.catch.call({ + then: {} + }); +}, 'ordinary object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js new file mode 100644 index 0000000000..190776f246 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js @@ -0,0 +1,35 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.catch +description: > + Promise.prototype.catch called with a `this` value whose `then` property is + an accessor property that returns an abrupt completion +info: | + 1. Let promise be the this value. + 2. Return ? Invoke(promise, "then", «undefined, onRejected»). + + 7.3.18 Invoke + + 1. Assert: IsPropertyKey(P) is true. + 2. If argumentsList was not passed, let argumentsList be a new empty List. + 3. Let func be ? GetV(V, P). + + 7.3.2 GetV + + 1. Assert: IsPropertyKey(P) is true. + 2. Let O be ? ToObject(V). + 3. Return ? O.[[Get]](P, V). +---*/ + +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + Promise.prototype.catch.call(poisonedThen); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js new file mode 100644 index 0000000000..39cd7cf5de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js @@ -0,0 +1,42 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.catch +description: > + Promise.prototype.catch called with a `this` value that defines a `then` + method which returns an abrupt completion. +info: | + 1. Let promise be the this value. + 2. Return ? Invoke(promise, "then", «undefined, onRejected»). + + 7.3.18 Invoke + + 1. Assert: IsPropertyKey(P) is true. + 2. If argumentsList was not passed, let argumentsList be a new empty List. + 3. Let func be ? GetV(V, P). + 4. Return ? Call(func, V, argumentsList). + + 7.3.2 GetV + + 1. Assert: IsPropertyKey(P) is true. + 2. Let O be ? ToObject(V). + 3. Return ? O.[[Get]](P, V). + + 7.3.12 Call (F, V [ , argumentsList ]) + + 1. If argumentsList was not passed, let argumentsList be a new empty List. + 2. If IsCallable(F) is false, throw a TypeError exception. + 3. Return ? F.[[Call]](V, argumentsList). +---*/ + +var thrower = { + then: function() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Promise.prototype.catch.call(thrower); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js new file mode 100644 index 0000000000..c4597f9cb8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js @@ -0,0 +1,69 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally invokes `then` method +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally, Reflect.construct, arrow-function] +includes: [isConstructor.js] +---*/ + +var target = new Promise(function() {}); +var returnValue = {}; +var callCount = 0; +var thisValue = null; +var argCount = null; +var resolve = null; +var reject = null; + +target.then = function(a, b) { + callCount += 1; + + thisValue = this; + argCount = arguments.length; + resolve = a; + reject = b; + + return returnValue; +}; + +var originalFinallyHandler = function() {}; +var result = Promise.prototype.finally.call(target, originalFinallyHandler, 2, 3); + +assert.sameValue(callCount, 1, 'The value of `callCount` is 1'); +assert.sameValue( + thisValue, + target, + 'The value of `thisValue` is expected to equal the value of target' +); +assert.sameValue(argCount, 2, 'The value of `argCount` is 2'); +assert.sameValue( + typeof resolve, + 'function', + 'The value of `typeof resolve` is "function"' +); +assert.notSameValue(resolve, originalFinallyHandler, 'The value of `resolve` is expected to not equal the value of `originalFinallyHandler`'); +assert.sameValue(resolve.length, 1, 'The value of resolve.length is 1'); +assert.sameValue(resolve.name, '', 'The value of resolve.name is ""'); +assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false'); +assert.throws(TypeError, () => { + new resolve(); +}, '`new resolve()` throws TypeError'); + + +assert.sameValue( + typeof reject, + 'function', + 'The value of `typeof reject` is "function"' +); +assert.notSameValue(reject, originalFinallyHandler, 'The value of `reject` is expected to not equal the value of `originalFinallyHandler`'); +assert.sameValue(reject.length, 1, 'The value of reject.length is 1'); +assert.sameValue(reject.name, '', 'The value of reject.name is ""'); +assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false'); +assert.throws(TypeError, () => { + new reject(); +}, '`new reject()` throws TypeError'); + +assert.sameValue(result, returnValue, 'The value of `result` is expected to equal the value of returnValue'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js new file mode 100644 index 0000000000..ca7b36445c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js @@ -0,0 +1,51 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally invokes `then` method +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +var target = new Promise(function() {}); +var returnValue = {}; +var callCount = 0; +var thisValue = null; +var argCount = null; +var firstArg = null; +var secondArg = null; +var result = null; + +target.then = function(a, b) { + callCount += 1; + + thisValue = this; + argCount = arguments.length; + firstArg = a; + secondArg = b; + + return returnValue; +}; + +result = Promise.prototype.finally.call(target, 1, 2, 3); + +assert.sameValue(callCount, 1, 'Invokes `then` method exactly once'); +assert.sameValue( + thisValue, + target, + 'Invokes `then` method with the instance as the `this` value' +); +assert.sameValue(argCount, 2, 'Invokes `then` method with exactly two single arguments'); +assert.sameValue( + firstArg, + 1, + 'Invokes `then` method with the provided non-callable first argument' +); +assert.sameValue( + secondArg, + 1, + 'Invokes `then` method with the provided non-callable first argument' +); +assert.sameValue(result, returnValue, 'Returns the result of the invocation of `then`'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js new file mode 100644 index 0000000000..19abfde2fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally is a function +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +assert.sameValue( + Promise.prototype.finally instanceof Function, + true, + 'Expected Promise.prototype.finally to be instanceof Function' +); + +assert.sameValue( + typeof Promise.prototype.finally, + 'function', + 'Expected Promise.prototype.finally to be a function' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js new file mode 100644 index 0000000000..741b127248 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js @@ -0,0 +1,18 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally is a method on a Promise +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +var p = Promise.resolve(3); + +assert.sameValue( + p.finally, + Promise.prototype.finally, + 'Expected the `finally` method on a Promise to be `Promise.prototype.finally`' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js new file mode 100644 index 0000000000..1146a91f1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally `length` property +esid: sec-promise.prototype.finally +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.prototype.finally] +---*/ + +verifyProperty(Promise.prototype.finally, "length", { + value: 1, + enumerable: false, + configurable: true, + writable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js new file mode 100644 index 0000000000..82020c1381 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally `name` property +esid: sec-promise.prototype.finally +info: | + ES Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Promise.prototype.finally] +---*/ + +assert.sameValue(Promise.prototype.finally.name, 'finally'); + +verifyNotEnumerable(Promise.prototype.finally, 'name'); +verifyNotWritable(Promise.prototype.finally, 'name'); +verifyConfigurable(Promise.prototype.finally, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js new file mode 100644 index 0000000000..25bb9a6554 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.prototype.finally does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Promise.prototype.finally, arrow-function] +---*/ + +assert.sameValue( + isConstructor(Promise.prototype.finally), + false, + 'isConstructor(Promise.prototype.finally) must return false' +); + +assert.throws(TypeError, () => { + let p = new Promise(() => {}); new p.finally(); +}, '`let p = new Promise(() => {}); new p.finally()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js new file mode 100644 index 0000000000..47d2f64fdd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise.prototype.finally property descriptor +esid: sec-promise.prototype.finally +info: | + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Promise.prototype.finally] +---*/ + +assert.sameValue(typeof Promise.prototype.finally, 'function'); + +verifyNotEnumerable(Promise.prototype, 'finally'); +verifyWritable(Promise.prototype, 'finally'); +verifyConfigurable(Promise.prototype, 'finally'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js new file mode 100644 index 0000000000..ecdbbdd164 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-catchfinallyfunctions +description: > + PromiseResolve() avoids extra Promise capability creation. +info: | + Catch Finally Functions + + [...] + 7. Let promise be ? PromiseResolve(C, result). + 8. Let thrower be equivalent to a function that throws reason. + 9. Return ? Invoke(promise, "then", « thrower »). + + PromiseResolve ( C, x ) + + 1. Assert: Type(C) is Object. + 2. If IsPromise(x) is true, then + a. Let xConstructor be ? Get(x, "constructor"). + b. If SameValue(xConstructor, C) is true, return x. +features: [Promise.prototype.finally] +flags: [async] +---*/ + +class MyPromise extends Promise {} + +var mp1Value = {}; +var mp1 = MyPromise.reject(mp1Value); +var mp2 = MyPromise.reject(42); + +var thenCalls = []; +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve, reject) { + thenCalls.push({promise: this, resolve, reject}); + return then.call(this, resolve, reject); +}; + +mp1.finally(() => mp2).then(value => { + throw new Test262Error("Expected the promise to be rejected, got resolved with " + value); +}, () => { + assert.sameValue(thenCalls.length, 5); + + var mp2Calls = thenCalls.filter(c => c.promise === mp2); + assert.sameValue(mp2Calls.length, 1); + assert.sameValue(mp2Calls[0].reject, undefined); + + var thrown = false; + try { + mp2Calls[0].resolve(); + } catch (error) { + thrown = true; + assert.sameValue(error, mp1Value); + } + + assert(thrown, "Expected resolve() to throw, but it didn't"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js new file mode 100644 index 0000000000..4d183bf248 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-catchfinallyfunctions +description: > + thrower is anonymous built-in function with length of 1 that throws reason. +info: | + Catch Finally Functions + + ... + 8. Let thrower be equivalent to a function that throws reason. + 9. Return ? Invoke(promise, "then", « thrower »). + + The "length" property of a Catch Finally function is 1. +features: [Promise.prototype.finally, Reflect.construct, class, arrow-function] +includes: [isConstructor.js] +flags: [async] +---*/ + +class MyError extends Error {} + +var myError = new MyError(); +Promise.reject(myError) + .finally(function() {}) + .then(function(value) { + $DONE('Expected promise to be rejected, got fulfilled with ' + value); + }, function(reason) { + if (reason === myError) { + $DONE(); + } else { + $DONE(reason); + } + }); + +var calls = 0; +var expected = [ + { length: 0, name: '' }, + { length: 1, name: '' } +]; + +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve, reject) { + + assert.sameValue( + resolve.length, + expected[calls].length, + 'The value of resolve.length is expected to equal the value of expected[calls].length' + ); + assert.sameValue( + resolve.name, + expected[calls].name, + 'The value of resolve.name is expected to equal the value of expected[calls].name' + ); + if (calls === 0) { + assert.throws(MyError, resolve, '`resolve()` throws `MyError`'); + assert.sameValue(arguments.length, 1, '`then` invoked with one argument'); + } else { + assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false'); + assert.throws(TypeError, () => { + new reject(); + }, '`new reject()` throws TypeError'); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + } + + calls += 1; + + return then.call(this, resolve, reject); +}; diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js new file mode 100644 index 0000000000..2d4dd9caaf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally observably calls .then +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +includes: [promiseHelper.js] +---*/ +var sequence = []; +var noReason = {}; +var no = Promise.reject(noReason); +no.then = function() { + sequence.push(1); + return Promise.prototype.then.apply(this, arguments); +}; + +var yesValue = {}; +var yes = Promise.resolve(yesValue); +yes.then = function() { + sequence.push(4); + return Promise.prototype.then.apply(this, arguments); +}; + +no.catch(function(e) { + sequence.push(2); + assert.sameValue(e, noReason); + throw e; +}).finally(function() { + sequence.push(3); + return yes; +}).catch(function(e) { + sequence.push(5); + assert.sameValue(e, noReason); +}).then(function() { + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "All expected callbacks called in correct order"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js new file mode 100644 index 0000000000..3903e7778b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js @@ -0,0 +1,30 @@ +// |reftest| async +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally on a rejected promise can not convert to a fulfillment +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +includes: [promiseHelper.js] +---*/ +var sequence = []; +var original = {}; +var replacement = {}; + +var p = Promise.reject(original); + +p.finally(function() { + sequence.push(1); + assert.sameValue(arguments.length, 0, 'onFinally receives zero args'); + return replacement; +}).then(function() { + throw new Test262Error('promise is rejected pre-finally; onFulfill should not be called'); +}).catch(function(reason) { + sequence.push(2); + assert.sameValue(reason, original, 'onFinally can not override the rejection value by returning'); +}).then(function() { + assert.sameValue(sequence.length, 2); + checkSequence(sequence, "All expected callbacks called in correct order"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js new file mode 100644 index 0000000000..66b6a468b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js @@ -0,0 +1,30 @@ +// |reftest| async +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally on a rejected promise can override the rejection reason +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +includes: [promiseHelper.js] +---*/ +var sequence = []; +var original = {}; +var thrown = {}; + +var p = Promise.reject(original); + +p.finally(function() { + sequence.push(1); + assert.sameValue(arguments.length, 0, 'onFinally receives zero args'); + throw thrown; +}).then(function() { + throw new Test262Error('promise is rejected; onFulfill should not be called'); +}).catch(function(reason) { + sequence.push(2); + assert.sameValue(reason, thrown, 'onFinally can override the rejection reason by throwing'); +}).then(function() { + assert.sameValue(sequence.length, 2); + checkSequence(sequence, "All expected callbacks called in correct order"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js new file mode 100644 index 0000000000..4951119385 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js @@ -0,0 +1,26 @@ +// |reftest| async +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally on a fulfilled promise can not override the resolution value +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +includes: [promiseHelper.js] +---*/ +var sequence = []; +var obj = {}; +var p = Promise.resolve(obj); + +p.finally(function() { + sequence.push(1); + assert.sameValue(arguments.length, 0, 'onFinally receives zero args'); + return {}; +}).then(function(x) { + sequence.push(2); + assert.sameValue(x, obj, 'onFinally can not override the resolution value'); +}).then(function() { + assert.sameValue(sequence.length, 2); + checkSequence(sequence, "All expected callbacks called in correct order"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js new file mode 100644 index 0000000000..137448ae6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-thenfinallyfunctions +description: > + PromiseResolve() avoids extra Promise capability creation. +info: | + Then Finally Functions + + [...] + 7. Let promise be ? PromiseResolve(C, result). + 8. Let valueThunk be equivalent to a function that returns value. + 9. Return ? Invoke(promise, "then", « valueThunk »). + + PromiseResolve ( C, x ) + + 1. Assert: Type(C) is Object. + 2. If IsPromise(x) is true, then + a. Let xConstructor be ? Get(x, "constructor"). + b. If SameValue(xConstructor, C) is true, return x. +features: [Promise.prototype.finally] +flags: [async] +---*/ + +class MyPromise extends Promise {} + +var mp1Value = {}; +var mp1 = MyPromise.resolve(mp1Value); +var mp2 = MyPromise.resolve(42); + +var thenCalls = []; +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve, reject) { + thenCalls.push({promise: this, resolve, reject}); + return then.call(this, resolve, reject); +}; + +mp1.finally(() => mp2).then(() => { + assert.sameValue(thenCalls.length, 5); + + var mp2Calls = thenCalls.filter(c => c.promise === mp2); + assert.sameValue(mp2Calls.length, 1); + assert.sameValue(mp2Calls[0].reject, undefined); + assert.sameValue(mp2Calls[0].resolve(), mp1Value); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js new file mode 100644 index 0000000000..ab7eedb192 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-thenfinallyfunctions +description: > + valueThunk is anonymous built-in function with length of 1 that returns value. +info: | + Then Finally Functions + + ... + 8. Let valueThunk be equivalent to a function that returns value. + 9. Return ? Invoke(promise, "then", « valueThunk »). + + The "length" property of a Then Finally function is 1. +features: [Promise.prototype.finally, Reflect.construct, arrow-function] +includes: [isConstructor.js] +flags: [async] +---*/ + +var value = {}; + +Promise.resolve(value) + .finally(function() {}) + .then(() => $DONE(), $DONE); + +var calls = 0; +var expected = [ + { length: 0, name: '' }, + { length: 1, name: '' } +]; + +var then = Promise.prototype.then; +Promise.prototype.then = function(resolve) { + assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false'); + assert.throws(TypeError, () => { + new resolve(); + }, '`new resolve()` throws TypeError'); + + assert.sameValue( + resolve.length, + expected[calls].length, + 'The value of resolve.length is expected to equal the value of expected[calls].length' + ); + assert.sameValue( + resolve.name, + expected[calls].name, + 'The value of resolve.name is expected to equal the value of expected[calls].name' + ); + if (calls === 0) { + assert.sameValue(resolve(), value, 'resolve() must return the value of value'); + } + calls += 1; + return then.call(this, resolve); +}; diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js new file mode 100644 index 0000000000..4f2341bfb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally observably calls .then +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +includes: [promiseHelper.js] +---*/ +var sequence = []; +var yesValue = {}; +var yes = Promise.resolve(yesValue); +yes.then = function() { + sequence.push(1); + return Promise.prototype.then.apply(this, arguments); +}; + +var noReason = {}; +var no = Promise.reject(noReason); +no.then = function() { + sequence.push(4); + return Promise.prototype.then.apply(this, arguments); +}; + +yes.then(function(x) { + sequence.push(2); + assert.sameValue(x, yesValue); + return x; +}).finally(function() { + sequence.push(3); + return no; +}).catch(function(e) { + sequence.push(5); + assert.sameValue(e, noReason); +}).then(function() { + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "All expected callbacks called in correct order"); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js new file mode 100644 index 0000000000..00c1127836 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright (C) 2017 V8. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Sathya Gunasekaran +description: finally calls the SpeciesConstructor and creates the right amount of promises +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +---*/ + + +var count = 0; +class FooPromise extends Promise { + constructor(resolve, reject) { + count++; + return super(resolve, reject); + } +} + +new FooPromise(r => r()) + .finally(() => {}) + .then(() => { + assert.sameValue(count, 7, "7 new promises were created"); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js new file mode 100644 index 0000000000..6bf6504a22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js @@ -0,0 +1,24 @@ +// |reftest| async +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise subclass finally on rejected creates the proper number of subclassed promises +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +---*/ + +var count = 0; +class FooPromise extends Promise { + constructor(resolve, reject) { + count++; + return super(resolve, reject); + } +} + +FooPromise.reject().finally(() => {}).then(value => { + throw new Test262Error("Expected Promise to be rejected, got: resolved with " + value); +}, () => { + assert.sameValue(count, 7); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js new file mode 100644 index 0000000000..6af753fa66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: Promise subclass finally on resolved creates the proper number of subclassed promises +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +flags: [async] +---*/ + +var count = 0; +class FooPromise extends Promise { + constructor(resolve, reject) { + count++; + return super(resolve, reject); + } +} + +FooPromise.resolve().finally(() => {}).then(() => { + assert.sameValue(count, 7); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js new file mode 100644 index 0000000000..9e9995fc91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally on rejected Promise calls the SpeciesConstructor +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +class FooPromise extends Promise { + static get[Symbol.species]() { + return Promise; + } +} + +var p = Promise.reject().finally(() => FooPromise.reject()); + +assert.sameValue(p instanceof Promise, true); +assert.sameValue(p instanceof FooPromise, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js new file mode 100644 index 0000000000..e5049b7349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: finally on resolved Promise calls the SpeciesConstructor +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +class FooPromise extends Promise { + static get[Symbol.species]() { + return Promise; + } +} + +var p = Promise.resolve().finally(() => FooPromise.resolve()); + +assert.sameValue(p instanceof Promise, true); +assert.sameValue(p instanceof FooPromise, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js new file mode 100644 index 0000000000..8c9ec2e7bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js @@ -0,0 +1,21 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: > + Promise.prototype.finally called with a non-object-coercible `this` value +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +assert.sameValue(typeof Promise.prototype.finally, 'function'); + +assert.throws(TypeError, function() { + Promise.prototype.finally.call(undefined); +}, 'undefined'); + +assert.throws(TypeError, function() { + Promise.prototype.finally.call(null); +}, 'null'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js new file mode 100644 index 0000000000..15ca9b1d7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: > + Promise.prototype.finally called with a non-branded Promise does not throw +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +var called = false; +var p = new Proxy(Promise.resolve(), {}); +var oldThen = Promise.prototype.then; +Promise.prototype.then = () => { + called = true; +}; +Promise.prototype.finally.call(p); +assert.sameValue(called, true); +Promise.prototype.then = oldThen; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js new file mode 100644 index 0000000000..ad5c687d6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js @@ -0,0 +1,56 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: > + Promise.prototype.finally called with a `this` value that does not define a + callable `then` property +esid: sec-promise.prototype.finally +features: [Symbol, Promise.prototype.finally] +---*/ +assert.sameValue(typeof Promise.prototype.finally, 'function'); + +var symbol = Symbol(); + +var thrower = function() { + throw new Test262Error('this should never happen'); +}; + +var p = new Promise(function() {}); + +p.then = undefined; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'undefined'); + +p.then = null; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'null'); + +p.then = 1; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'number'); + +p.then = ''; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'string'); + +p.then = true; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'boolean'); + +p.then = symbol; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'symbol'); + +p.then = {}; +assert.throws(TypeError, function() { + Promise.prototype.finally.call(p, thrower); +}, 'ordinary object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js new file mode 100644 index 0000000000..44e4173989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js @@ -0,0 +1,26 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: > + Promise.prototype.finally called with a `this` value whose `then` property is + an accessor property that returns an abrupt completion +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +var poisonedThen = Object.defineProperty(new Promise(function() {}), 'then', { + get: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + Promise.prototype.finally.call(poisonedThen); +}); + +assert.throws(Test262Error, function() { + poisonedThen.finally(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js new file mode 100644 index 0000000000..536ed24171 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js @@ -0,0 +1,25 @@ +// Copyright (C) 2017 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +author: Jordan Harband +description: > + Promise.prototype.finally called with a `this` value that defines a `then` + method which returns an abrupt completion. +esid: sec-promise.prototype.finally +features: [Promise.prototype.finally] +---*/ + +var thrower = new Promise(function() {}); +thrower.then = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.prototype.finally.call(thrower); +}); + +assert.throws(Test262Error, function() { + thrower.finally(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js new file mode 100644 index 0000000000..dccb5be50c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js @@ -0,0 +1,19 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype.finally +description: > + Promise.prototype.finally invoked on thenable returns result of "then" call. +features: [Promise.prototype.finally] +---*/ + +var thenResult = {}; +var Thenable = function() {}; +Thenable.prototype.then = function() { return thenResult; }; + +assert.sameValue( + Promise.prototype.finally.call(new Thenable()), + thenResult +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js b/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js new file mode 100644 index 0000000000..096249ac1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-properties-of-the-promise-prototype-object +description: Promise.prototype does not have a [[PromiseState]] internal slot +info: | + The Promise prototype object is the intrinsic object %PromisePrototype%. The + value of the [[Prototype]] internal slot of the Promise prototype object is + the intrinsic object %ObjectPrototype%. The Promise prototype object is an + ordinary object. It does not have a [[PromiseState]] internal slot or any of + the other internal slots of Promise instances. + + 25.4.5.3 Promise.prototype.then + + 1. Let promise be the this value. + 2. If IsPromise(promise) is false, throw a TypeError exception. + + 25.4.1.6 IsPromise + + 1. If Type(x) is not Object, return false. + 2. If x does not have a [[PromiseState]] internal slot, return false. +---*/ + +assert.throws(TypeError, function() { + Promise.prototype.then.call(Promise.prototype, function() {}, function() {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js new file mode 100644 index 0000000000..b369a731ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js @@ -0,0 +1,16 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.prototype +description: Property descriptor of 'prototype' property +info: | + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: false }. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'prototype'); +verifyNotWritable(Promise, 'prototype'); +verifyNotConfigurable(Promise, 'prototype'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/proto.js b/js/src/tests/test262/built-ins/Promise/prototype/proto.js new file mode 100644 index 0000000000..d0fb702c39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/proto.js @@ -0,0 +1,16 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-properties-of-the-promise-prototype-object +description: Promise.prototype [[Prototype]] is %ObjectPrototype% +info: | + The Promise prototype object is the intrinsic object %PromisePrototype%. The + value of the [[Prototype]] internal slot of the Promise prototype object is + the intrinsic object %ObjectPrototype%. The Promise prototype object is an + ordinary object. It does not have a [[PromiseState]] internal slot or any of + the other internal slots of Promise instances. +---*/ + +assert.sameValue(Object.getPrototypeOf(Promise.prototype), Object.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js new file mode 100644 index 0000000000..30133bb896 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Misc sequencing tests + inspired by https://github.com/getify/native-promise-only/issues/34#issuecomment-54282002 +es6id: S25.4.2.1_A3.2_T2 +author: Sam Mikes +description: Promise onResolved functions are called in predictable sequence +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p = new Promise(function(resolve, reject) { + sequence.push(1); + resolve(""); +}); + +p.then(function() { + sequence.push(3); +}).then(function() { + sequence.push(5); +}).then(function() { + sequence.push(7); +}); + +p.then(function() { + sequence.push(4); +}).then(function() { + sequence.push(6); +}).then(function() { + sequence.push(8); +}).then(function() { + assert.sameValue(sequence.length, 8); + checkSequence(sequence, "Sequence should be as expected"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js new file mode 100644 index 0000000000..2b504506bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Misc sequencing tests + inspired by https://github.com/promises-aplus/promises-tests/issues/61 + Case "T1" +es6id: S25.4.4_A2.1_T1 +author: Sam Mikes +description: Promise onResolved functions are called in predictable sequence +includes: [promiseHelper.js] +flags: [async] +---*/ + +var resolveP1, rejectP2, sequence = []; + +(new Promise(function(resolve, reject) { + resolveP1 = resolve; +})).then(function(msg) { + sequence.push(msg); +}).then(function() { + assert.sameValue(sequence.length, 3); +checkSequence(sequence, "Expected 1,2,3"); +}).then($DONE, $DONE); + +(new Promise(function(resolve, reject) { + rejectP2 = reject; +})).catch(function(msg) { + sequence.push(msg); +}); + +rejectP2(2); +resolveP1(3); + +sequence.push(1); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js new file mode 100644 index 0000000000..c689e07f99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Misc sequencing tests + inspired by https://github.com/promises-aplus/promises-tests/issues/61 + Case "T2a" +es6id: S25.4.4_A2.1_T2 +author: Sam Mikes +description: Promise onResolved functions are called in predictable sequence +includes: [promiseHelper.js] +flags: [async] +---*/ + +var resolveP1, rejectP2, p1, p2, + sequence = []; + +p1 = new Promise(function(resolve, reject) { + resolveP1 = resolve; +}); +p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; +}); + +rejectP2(3); +resolveP1(2); + +p1.then(function(msg) { + sequence.push(msg); +}); + +p2.catch(function(msg) { + sequence.push(msg); +}).then(function() { + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "Expected 1,2,3"); +}).then($DONE, $DONE); + +sequence.push(1); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js new file mode 100644 index 0000000000..dc1f0d7233 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Misc sequencing tests + inspired by https://github.com/promises-aplus/promises-tests/issues/61 + Case "T2b" +es6id: S25.4.4_A2.1_T3 +author: Sam Mikes +description: Promise onResolved functions are called in predictable sequence +includes: [promiseHelper.js] +flags: [async] +---*/ + +var resolveP1, rejectP2, p1, p2, + sequence = []; + +p1 = new Promise(function(resolve, reject) { + resolveP1 = resolve; +}); +p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; +}); + +rejectP2(3); +resolveP1(2); + +Promise.resolve().then(function() { + p1.then(function(msg) { + sequence.push(msg); + }); + + p2.catch(function(msg) { + sequence.push(msg); + }).then(function() { + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "Expected 1,2,3"); + }).then($DONE, $DONE); +}); + +sequence.push(1); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js new file mode 100644 index 0000000000..959bc284dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js @@ -0,0 +1,16 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.then is a function of two arguments +es6id: S25.4.5.3_A1.1_T1 +author: Sam Mikes +description: Promise.prototype.then is a function of two arguments +---*/ +assert( + !!(Promise.prototype.then instanceof Function), + 'The value of !!(Promise.prototype.then instanceof Function) is expected to be true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js new file mode 100644 index 0000000000..c89023e083 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js @@ -0,0 +1,17 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.then is a function of two arguments +es6id: S25.4.5.3_A1.1_T2 +author: Sam Mikes +description: Promise.prototype.then is a function of two arguments +---*/ + +var p = new Promise(function() {}); + +assert(!!(p.then instanceof Function), 'The value of !!(p.then instanceof Function) is expected to be true'); +assert.sameValue(p.then.length, 2, 'The value of p.then.length is expected to be 2'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js new file mode 100644 index 0000000000..a4e20bae96 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js @@ -0,0 +1,18 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.then expects a constructor conforming to Promise as 'this' +es6id: S25.4.5.3_A2.1_T1 +author: Sam Mikes +description: Promise.prototype.then throw if 'this' is non-Object +---*/ + +var p = new Promise(function() {}); + +assert.throws(TypeError, function() { + p.then.call(3, function() {}, function() {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js new file mode 100644 index 0000000000..4a982b5675 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js @@ -0,0 +1,20 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.then expects a Promise as 'this' +es6id: S25.4.5.3_A2.1_T2 +author: Sam Mikes +description: Promise.prototype.then throw if 'this' is non-Promise Object +---*/ + +function ZeroArgConstructor() {} + +var z = new ZeroArgConstructor(); + +assert.throws(TypeError, function() { + Promise.then.call(z, function() {}, function() {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js new file mode 100644 index 0000000000..8fc66ab964 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js @@ -0,0 +1,21 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A4.1_T1 +author: Sam Mikes +description: Promise.prototype.then accepts 'undefined' as arg1, arg2 +flags: [async] +---*/ + +var arg = {}; +var p = Promise.resolve(arg); + +p.then(undefined, undefined) + .then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js new file mode 100644 index 0000000000..3aeca23d95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A4.1_T2 +author: Sam Mikes +description: Promise.prototype.then accepts 'undefined' as arg1, arg2 +flags: [async] +---*/ + +var arg = {}; +var p = Promise.reject(arg); + +p.then(undefined, undefined).then(function() { + throw new Test262Error("Should not be called -- promise was rejected."); +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js new file mode 100644 index 0000000000..5b1ac21b27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js @@ -0,0 +1,21 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A4.2_T1 +author: Sam Mikes +description: Promise.prototype.then treats non-callable arg1, arg2 as undefined +flags: [async] +---*/ + +var arg = {}; +var p = Promise.resolve(arg); + +p.then(3, 5) + .then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js new file mode 100644 index 0000000000..5efe836020 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A4.2_T2 +author: Sam Mikes +description: Promise.prototype.then treats non-callable arg1, arg2 as undefined +flags: [async] +---*/ + +var arg = {}; +var p = Promise.reject(arg); + +p.then(3, 5).then(function() { + throw new Test262Error("Should not be called -- promise was rejected."); +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js new file mode 100644 index 0000000000..2f0b062fae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A5.1_T1 +author: Sam Mikes +description: Promise.prototype.then enqueues handler if pending +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = [], + pResolve, + p = new Promise(function(resolve, reject) { + pResolve = resolve; + }); + +sequence.push(1); + +p.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "Should be second"); +}).catch($DONE); + +Promise.resolve().then(function() { + // enqueue another then-handler + p.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "Should be third"); + }).then($DONE, $DONE); + + sequence.push(2); + assert.sameValue(sequence.length, 2); + checkSequence(sequence, "Should be first"); + + pResolve(); +}).catch($DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js new file mode 100644 index 0000000000..6e09de73a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A5.2_T1 +author: Sam Mikes +description: Promise.prototype.then immediately queues handler if fulfilled +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = [], + pResolve, + p = new Promise(function(resolve, reject) { + pResolve = resolve; + }); + +sequence.push(1); + +pResolve(); + +p.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); +checkSequence(sequence, "Should be first"); +}).catch($DONE); + +Promise.resolve().then(function() { + // enqueue another then-handler + p.then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); +checkSequence(sequence, "Should be third"); + }).then($DONE, $DONE); + + sequence.push(4); + assert.sameValue(sequence.length, 4); +checkSequence(sequence, "Should be second"); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js new file mode 100644 index 0000000000..87a2b2271b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + PerformPromiseThen + Ref 25.4.5.3.1 +es6id: S25.4.5.3_A5.3_T1 +author: Sam Mikes +description: Promise.prototype.then immediately queues handler if rejected +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = [], + pReject, + p = new Promise(function(resolve, reject) { + pReject = reject; + }); + +sequence.push(1); + +pReject(); + +p.then(function() { + throw new Test262Error("Should not be called -- Promise rejected."); +}, function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "Should be first"); +}).catch($DONE); + +Promise.resolve().then(function() { + // enqueue another then-handler + p.then(function() { + throw new Test262Error("Should not be called (2) -- Promise rejected."); + }, function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "Should be third"); + }).then($DONE, $DONE); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "Should be second"); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js new file mode 100644 index 0000000000..de6cea8025 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js @@ -0,0 +1,99 @@ +// 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. + ... +features: [class] +---*/ + +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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js new file mode 100644 index 0000000000..ed3dee89ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js @@ -0,0 +1,104 @@ +// 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. + ... +features: [class] +---*/ + +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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js b/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js new file mode 100644 index 0000000000..794407fa72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js @@ -0,0 +1,26 @@ +// 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() { + throw new Test262Error("get constructor called"); + } +}; + +assert.throws(TypeError, function() { + Promise.prototype.then.call(object); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js new file mode 100644 index 0000000000..9c54c46ac4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: The instance's `constructor` property is accessed exactly once +info: | + 1. Let promise be the this value. + 2. If IsPromise(promise) is false, throw a TypeError exception. + 3. Let C be SpeciesConstructor(promise, %Promise%). + 4. ReturnIfAbrupt(C). + 5. Let resultCapability be NewPromiseCapability(C). + 6. ReturnIfAbrupt(resultCapability). + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 7.3.20 SpeciesConstructor ( O, defaultConstructor ) + + 1. Assert: Type(O) is Object. + 2. Let C be Get(O, "constructor"). + 3. ReturnIfAbrupt(C). + 4. If C is undefined, return defaultConstructor. + 5. If Type(C) is not Object, throw a TypeError exception. + 6. Let S be Get(C, @@species). + 7. ReturnIfAbrupt(S). + 8. If S is either undefined or null, return defaultConstructor. + 9. If IsConstructor(S) is true, return S. + 10. Throw a TypeError exception. +flags: [async] +---*/ + +var callCount = 0; +var prms = new Promise(function(resolve) { + resolve(); +}); +Object.defineProperty(prms, 'constructor', { + get: function() { + callCount += 1; + return Promise; + } +}); + +prms.then(function() { + if (callCount !== 1) { + $DONE('Expected constructor access count: 1. Actual: ' + callCount); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js new file mode 100644 index 0000000000..0ad80c7513 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js @@ -0,0 +1,51 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: The constructor defined by Symbol.species takes precedence +info: | + 1. Let promise be the this value. + 2. If IsPromise(promise) is false, throw a TypeError exception. + 3. Let C be SpeciesConstructor(promise, %Promise%). + 4. ReturnIfAbrupt(C). + 5. Let resultCapability be NewPromiseCapability(C). +features: [Symbol.species, class] +---*/ + +var callCount = 0; +var thisValue, firstArg, argLength, getCapabilitiesExecutor; +var executor = function() {}; +var p1 = new Promise(function() {}); +var SpeciesConstructor = class extends Promise { + constructor(a) { + super(a); + callCount += 1; + thisValue = this; + getCapabilitiesExecutor = a; + argLength = arguments.length; + } +}; +var p2; + +p1.constructor = function() {}; +p1.constructor[Symbol.species] = SpeciesConstructor; + +p2 = p1.then(); + +assert.sameValue(callCount, 1, 'The constructor is invoked exactly once'); +assert(thisValue instanceof SpeciesConstructor); +assert.sameValue( + argLength, 1, 'The constructor is invoked with a single argument' +); +assert.sameValue(typeof getCapabilitiesExecutor, 'function'); +assert.sameValue( + getCapabilitiesExecutor.length, + 2, + 'ES6 25.4.1.5.1: The length property of a GetCapabilitiesExecutor function is 2.' +); +assert( + p2 instanceof SpeciesConstructor, + 'The returned object is an instance of the constructor' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js new file mode 100644 index 0000000000..a0b6df2a9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: > + A TypeError is thrown when the `this` value has a non-object `constructor` property +info: | + 1. Let promise be the this value. + 2. If IsPromise(promise) is false, throw a TypeError exception. + 3. Let C be SpeciesConstructor(promise, %Promise%). + 4. ReturnIfAbrupt(C). + 5. Let resultCapability be NewPromiseCapability(C). +---*/ + +var p = new Promise(function() {}); +p.constructor = null; + +assert.throws(TypeError, function() { + p.then(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js new file mode 100644 index 0000000000..c0bb06362d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js @@ -0,0 +1,29 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.prototype.then throws TypeError if Get(promise, "constructor") throws + Ref 25.4.5.3 step 4 ReturnIfAbrupt(C) +es6id: S25.4.5.3_A3.1_T1 +author: Sam Mikes +description: Promise.prototype.then throws if Get(promise, "constructor") throws +---*/ + +var p = Promise.resolve("foo"); + +Object.defineProperty(p, "constructor", { + get: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + p.then(function() { + throw new Test262Error("Should never be called."); + }, function() { + throw new Test262Error("Should never be called."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js new file mode 100644 index 0000000000..d54621103e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.prototype.then` invoked on a constructor value that throws an + error +es6id: 25.4.5.3 +info: | + 1. Let promise be the this value. + [...] + 3. Let C be SpeciesConstructor(promise, %Promise%). + [...] + 5. Let resultCapability be NewPromiseCapability(C). + 6. ReturnIfAbrupt(resultCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). + features: [Symbol.species] +---*/ + +var BadCtor = function() { + throw new Test262Error(); +}; +var originalSpecies = Object.getOwnPropertyDescriptor(Promise, Symbol.species); + +Object.defineProperty(Promise, Symbol.species, { + value: BadCtor +}); + +try { + var p = new Promise(function(resolve) { + resolve(); + }); + + assert.throws(Test262Error, function() { + p.then(); + }); +} finally { + Object.defineProperty(Promise, Symbol.species, originalSpecies); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js new file mode 100644 index 0000000000..513f9d6cb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: > + The Promise built-in is used when the `this` value has no `constructor` property +info: | + 1. Let promise be the this value. + 2. If IsPromise(promise) is false, throw a TypeError exception. + 3. Let C be SpeciesConstructor(promise, %Promise%). + 4. ReturnIfAbrupt(C). + 5. Let resultCapability be NewPromiseCapability(C). +---*/ + +var p1 = new Promise(function() {}); +delete p1.constructor; + +var p2 = p1.then(); + +assert(p2 instanceof Promise); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js b/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js new file mode 100644 index 0000000000..fd2f6f1cf5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js @@ -0,0 +1,68 @@ +// |reftest| async +// 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). +features: [class] +flags: [async] +---*/ + +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/js/src/tests/test262/built-ins/Promise/prototype/then/length.js b/js/src/tests/test262/built-ins/Promise/prototype/then/length.js new file mode 100644 index 0000000000..1e865b0460 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: Promise.prototype.then `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.prototype.then.length, 2); + +verifyNotEnumerable(Promise.prototype.then, 'length'); +verifyNotWritable(Promise.prototype.then, 'length'); +verifyConfigurable(Promise.prototype.then, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/name.js b/js/src/tests/test262/built-ins/Promise/prototype/then/name.js new file mode 100644 index 0000000000..b1c97f9956 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: Promise.prototype.then `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.prototype.then.name, 'then'); + +verifyNotEnumerable(Promise.prototype.then, 'name'); +verifyNotWritable(Promise.prototype.then, 'name'); +verifyConfigurable(Promise.prototype.then, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js new file mode 100644 index 0000000000..d943772f86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.prototype.then does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue( + isConstructor(Promise.prototype.then), + false, + 'isConstructor(Promise.prototype.then) must return false' +); + +assert.throws(TypeError, () => { + let p = new Promise(() => {}); new p.then(); +}, '`let p = new Promise(() => {}); new p.then()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js new file mode 100644 index 0000000000..89d5e2de5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: PerformPromiseThen on a fulfilled promise +info: | + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + + [...] + 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»). + [...] +flags: [async] +---*/ + +var value = {}; +var p = new Promise(function(resolve) { + resolve(value); +}); + +p.then(function(x) { + if (x !== value) { + $DONE('The `onFulfilled` handler should be invoked with the promise result.'); + return; + } + $DONE(); +}, function() { + $DONE('The `onRejected` handler should not be invoked.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js new file mode 100644 index 0000000000..93204370cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: PerformPromiseThen on a pending promise that is later fulfilled +info: | + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] +flags: [async] +---*/ + +var value = {}; +var resolve; +var p = new Promise(function(_resolve) { + resolve = _resolve; +}); + +p.then(function(x) { + if (x !== value) { + $DONE('The `onFulfilled` handler should be invoked with the promise result.'); + return; + } + $DONE(); +}, function() { + $DONE('The `onRejected` handler should not be invoked.'); +}); + +resolve(value); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js new file mode 100644 index 0000000000..b65b5596ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: PerformPromiseThen on a pending promise that is later rejected +info: | + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] +flags: [async] +---*/ + +var value = {}; +var reject; +var p = new Promise(function(_, _reject) { + reject = _reject; +}); + +p.then(function() { + $DONE('The `onFulfilled` handler should not be invoked.'); +}, function(x) { + if (x !== value) { + $DONE('The `onRejected` handler should be invoked with the promise result.'); + return; + } + $DONE(); +}); + +reject(value); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js new file mode 100644 index 0000000000..4b74b5f3cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.3 +description: PerformPromiseThen on a rejected promise +info: | + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + [...] +flags: [async] +---*/ + +var value = {}; +var p = new Promise(function(_, reject) { + reject(value); +}); + +p.then(function() { + $DONE('The `onFulfilled` handler should not be invoked.'); +}, function(x) { + if (x !== value) { + $DONE('The `onRejected` handler should be invoked with the promise result.'); + return; + } + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js new file mode 100644 index 0000000000..75e58c3117 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: Promise.prototype.then property descriptor +info: | + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(typeof Promise.prototype.then, 'function'); + +verifyNotEnumerable(Promise.prototype, 'then'); +verifyWritable(Promise.prototype, 'then'); +verifyConfigurable(Promise.prototype, 'then'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js new file mode 100644 index 0000000000..7795f1bb2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var resolve; +var thenable = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + throw thenable; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js new file mode 100644 index 0000000000..72c27c684c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var reject; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + throw thenable; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js new file mode 100644 index 0000000000..56dbd6fff3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + throw thenable; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js new file mode 100644 index 0000000000..0f87c6bb01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + throw thenable; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js new file mode 100644 index 0000000000..fd6602988b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var resolve; +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +p2 = p1.then(function() { + return 23; +}); + +p2.then(function(value) { + if (value !== 23) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js new file mode 100644 index 0000000000..e71b639f39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var nonThenable = { + then: null +}; +var resolve; +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +p2 = p1.then(function() { + return nonThenable; +}); + +p2.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js new file mode 100644 index 0000000000..88c3cd57a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var resolve; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +p2 = p1.then(function() { + return poisonedThen; +}); + +p2.then(function(x) { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== value) { + $DONE('The promise should be rejected with the thrown exception.'); + return; + } + + $DONE(); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js new file mode 100644 index 0000000000..147ce71f22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js @@ -0,0 +1,61 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var resolve; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +thenable.then = function(resolve) { + resolve(value); +}; + +p2 = p1.then(function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js new file mode 100644 index 0000000000..1191706a68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var resolve; +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +p2 = p1.then(function() { + return p2; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(reason) { + if (!reason) { + $DONE('The promise should be rejected with a value.'); + return; + } + + if (reason.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js new file mode 100644 index 0000000000..52ad8d2366 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value from a pending promise that is later fulfilled +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + a. Append fulfillReaction as the last element of the List that is the + value of promise's [[PromiseFulfillReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var resolve; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var p1 = new Promise(function(_resolve) { + resolve = _resolve; +}); +var p2; + +p2 = p1.then(function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +resolve(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js new file mode 100644 index 0000000000..1480ad1f5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var reject; +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + return 23; +}); + +p2.then(function(value) { + if (value !== 23) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js new file mode 100644 index 0000000000..19764d8de7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var nonThenable = { + then: null +}; +var reject; +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + return nonThenable; +}); + +p2.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js new file mode 100644 index 0000000000..542c6e7ead --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var reject; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + return poisonedThen; +}); + +p2.then(function(x) { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== value) { + $DONE('The promise should be rejected with the thrown exception.'); + return; + } + + $DONE(); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js new file mode 100644 index 0000000000..4a3fbc1674 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js @@ -0,0 +1,62 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var reject; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +thenable.then = function(resolve) { + resolve(value); +}; + +p2 = p1.then(function() {}, function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js new file mode 100644 index 0000000000..7a31dc46bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var reject; +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + return p2; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(reason) { + if (!reason) { + $DONE('The promise should be rejected with a value.'); + return; + } + + if (reason.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js new file mode 100644 index 0000000000..775bb1f79f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value from a pending promise that is later rejected +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 7. If the value of promise's [[PromiseState]] internal slot is "pending", + [...] + b. Append rejectReaction as the last element of the List that is the + value of promise's [[PromiseRejectReactions]] internal slot. + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var reject; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var p1 = new Promise(function(_, _reject) { + reject = _reject; +}); +var p2; + +p2 = p1.then(function() {}, function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +reject(); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js new file mode 100644 index 0000000000..5f6494fa3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return 23; +}); + +p2.then(function(value) { + if (value !== 23) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js new file mode 100644 index 0000000000..3ca031489f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var nonThenable = { + then: null +}; +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return nonThenable; +}); + +p2.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js new file mode 100644 index 0000000000..ab5ee4a727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return poisonedThen; +}); + +p2.then(function(x) { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== value) { + $DONE('The promise should be rejected with the thrown exception.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js new file mode 100644 index 0000000000..5594511e34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +thenable.then = function(resolve) { + resolve(value); +}; + +p2 = p1.then(function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js new file mode 100644 index 0000000000..89c4f064b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return p2; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(reason) { + if (!reason) { + $DONE('The promise should be rejected with a value.'); + return; + } + + if (reason.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js new file mode 100644 index 0000000000..f978984c36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js @@ -0,0 +1,61 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value from a fulfilled promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js new file mode 100644 index 0000000000..1d39308386 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return 23; +}); + +p2.then(function(value) { + if (value !== 23) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js new file mode 100644 index 0000000000..eae6797f1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var nonThenable = { + then: null +}; +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return nonThenable; +}); + +p2.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js new file mode 100644 index 0000000000..2f33c820bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return poisonedThen; +}); + +p2.then(function(x) { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== value) { + $DONE('The promise should be rejected with the thrown exception.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js new file mode 100644 index 0000000000..303a5315b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +thenable.then = function(resolve) { + resolve(value); +}; + +p2 = p1.then(function() {}, function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js new file mode 100644 index 0000000000..a585ca9b2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return p2; +}); + +p2.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(reason) { + if (!reason) { + $DONE('The promise should be rejected with a value.'); + return; + } + + if (reason.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js new file mode 100644 index 0000000000..827ff855f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js @@ -0,0 +1,61 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value from a rejected promise +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return thenable; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The promise should be fulfilled with the resolution value of the provided promise.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js new file mode 100644 index 0000000000..61fd431b65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + [...] + 6. Else, let handlerResult be Call(handler, undefined, «argument»). +es6id: S25.4.2.1_A3.1_T1 +author: Sam Mikes +description: > + "fulfilled" handler invoked correctly outside of strict mode +flags: [async, noStrict] +---*/ + +var expectedThis = this, + obj = {}; + +var p = Promise.resolve(obj).then(function(arg) { + if (this !== expectedThis) { + $DONE("'this' must be global object, got " + this); + return; + } + + if (arg !== obj) { + $DONE("Expected promise to be fulfilled by obj, actually " + arg); + return; + } + + if (arguments.length !== 1) { + $DONE('Expected handler function to be called with exactly 1 argument.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js new file mode 100644 index 0000000000..3c0ab9a54d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js @@ -0,0 +1,39 @@ +// |reftest| async +'use strict'; +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + [...] + 6. Else, let handlerResult be Call(handler, undefined, «argument»). +es6id: S25.4.2.1_A3.1_T2 +author: Sam Mikes +description: > + "fulfilled" handler invoked correctly in strict mode +flags: [async, onlyStrict] +---*/ + +var expectedThis = undefined, + obj = {}; + +var p = Promise.resolve(obj).then(function(arg) { + if (this !== expectedThis) { + $DONE("'this' must be undefined, got " + this); + return; + } + + if (arg !== obj) { + $DONE("Expected promise to be fulfilled by obj, actually " + arg); + return; + } + + if (arguments.length !== 1) { + $DONE('Expected handler function to be called with exactly 1 argument.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js new file mode 100644 index 0000000000..ec9ab0172b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completions should not preclude additional jobs +es6id: 25.4.2.1 +info: | + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var promise = new Promise(function(resolve) { + resolve(); +}); +var fulfilledCallCount = 0; +var rejectedCallCount = 0; + +promise.then(function() { + fulfilledCallCount += 1; + throw new Error(); +}, function() { + rejectedCallCount += 1; +}); + +promise.then(function() { + if (fulfilledCallCount !== 1) { + $DONE('Expected "onFulfilled" handler to be invoked exactly once.'); + return; + } + + if (rejectedCallCount !== 0) { + $DONE('Expected "onRejected" handler to not be invoked.'); + return; + } + + $DONE(); +}, function() { + $DONE('This promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js new file mode 100644 index 0000000000..13fb4ca62f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: All queued jobs should be executed in series +es6id: 25.4.2.1 +info: | + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var promise = new Promise(function(resolve) { + resolve(); +}); +var log = ''; + +promise.then(function() { + log += 'a'; +}, function() { + log += 'A'; +}); + +promise.then(function() { + log += 'b'; +}, function() { + log += 'B'; +}); + +promise.then(function() { + log += 'c'; +}, function() { + log += 'C'; +}); + +promise.then(function() { + if (log !== 'abc') { + $DONE( + 'Expected each "onFulfilled" handler to be invoked exactly once in series. ' + + 'Expected: abc. Actual: ' + log + ); + return; + } + + $DONE(); +}, function() { + $DONE('This promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js new file mode 100644 index 0000000000..a394847ce9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: An abrupt completion should trigger promise rejection +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var value = {}; +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + throw value; +}, function() {}); + +p2.then(function() { + $DONE('The `onFulfilled` handler should not be invoked.'); +}, function(x) { + if (x !== value) { + $DONE('The `onRejected` handler should be invoked with the promise result.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js new file mode 100644 index 0000000000..5acd838f06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: A normal completion should trigger promise fulfillment +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 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. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, + value»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var value = {}; +var p1 = new Promise(function(resolve) { + resolve(); +}); +var p2; + +p2 = p1.then(function() { + return value; +}, function() {}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The `onFulfilled` handler should be invoked with the promise result.'); + return; + } + + $DONE(); +}, function() { + $DONE('The `onRejected` handler should not be invoked.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js new file mode 100644 index 0000000000..d559176177 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise reaction jobs have predictable environment +es6id: S25.4.2.1_A1.1_T1 +author: Sam Mikes +description: argument passes through "Identity" +flags: [async] +---*/ + +var obj = {}; + +var p = Promise.resolve(obj).then( /*Identity, Thrower*/ ) + .then(function(arg) { + if (arg !== obj) { + $DONE("Expected promise to be fulfilled with obj, actually " + arg); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js new file mode 100644 index 0000000000..0b548a01f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + [...] + 6. Else, let handlerResult be Call(handler, undefined, «argument»). +es6id: S25.4.2.1_A3.2_T1 +author: Sam Mikes +description: > + "rejected" handler invoked correctly outside of strict mode +flags: [async, noStrict] +---*/ + +var expectedThis = this, + obj = {}; + +var p = Promise.reject(obj).then(function() { + $DONE("Unexpected fulfillment; expected rejection."); +}, function(arg) { + if (this !== expectedThis) { + $DONE("'this' must be global object, got " + this); + return; + } + + if (arg !== obj) { + $DONE("Expected promise to be rejected with obj, actually " + arg); + return; + } + + if (arguments.length !== 1) { + $DONE('Expected handler function to be called with exactly 1 argument.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js new file mode 100644 index 0000000000..09f0954c0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js @@ -0,0 +1,39 @@ +// |reftest| async +'use strict'; +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + [...] + 6. Else, let handlerResult be Call(handler, undefined, «argument»). +es6id: S25.4.2.1_A3.2_T2 +author: Sam Mikes +description: > + "rejected" handler invoked correctly in strict mode +flags: [async, onlyStrict] +---*/ + +var expectedThis = undefined, + obj = {}; + +var p = Promise.reject(obj).then(function() { + $DONE("Unexpected fulfillment; expected rejection."); +}, function(arg) { + if (this !== expectedThis) { + $DONE("'this' must be undefined, got " + this); + return; + } + + if (arg !== obj) { + $DONE("Expected promise to be rejected with obj, actually " + arg); + return; + } + + if (arguments.length !== 1) { + $DONE('Expected handler function to be called with exactly 1 argument.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js new file mode 100644 index 0000000000..681f4fabc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completions should not preclude additional jobs +es6id: 25.4.2.1 +info: | + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var promise = new Promise(function(_, reject) { + reject(); +}); +var fulfilledCallCount = 0; +var rejectedCallCount = 0; + +promise.then(function() { + fulfilledCallCount += 1; +}, function() { + rejectedCallCount += 1; + throw new Error(); +}); + +promise.then(function() { + $DONE('This promise should not be fulfilled.'); +}, function() { + if (fulfilledCallCount !== 0) { + $DONE('Expected "onFulfilled" handler to not be invoked.'); + return; + } + + if (rejectedCallCount !== 1) { + $DONE('Expected "onRejected" handler to be invoked exactly once.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js new file mode 100644 index 0000000000..d88d3e1a48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: All queued jobs should be executed in series +es6id: 25.4.2.1 +info: | + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var promise = new Promise(function(_, reject) { + reject(); +}); +var log = ''; + +promise.then(function() { + log += 'A'; +}, function() { + log += 'a'; +}); + +promise.then(function() { + log += 'B'; +}, function() { + log += 'b'; +}); + +promise.then(function() { + log += 'C'; +}, function() { + log += 'c'; +}); + +promise.then(function() { + $DONE('This promise should not be fulfilled.'); +}, function() { + if (log !== 'abc') { + $DONE( + 'Expected each "onFulfilled" handler to be invoked exactly once in series. ' + + 'Expected: abc. Actual: ' + log + ); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js new file mode 100644 index 0000000000..8b89456853 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: An abrupt completion should trigger promise rejection +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var value = {}; +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + throw value; +}); + +p2.then(function() { + $DONE('The `onFulfilled` handler should not be invoked.'); +}, function(x) { + if (x !== value) { + $DONE('The `onRejected` handler should be invoked with the promise result.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js new file mode 100644 index 0000000000..d29489baa8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: A normal completion should trigger promise fulfillment +es6id: 25.4.5.3 +info: | + [...] + 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, + resultCapability). + + 25.4.5.3.1 PerformPromiseThen + [...] + 9. Else if the value of promise's [[PromiseState]] internal slot is + "rejected", + a. Let reason be the value of promise's [[PromiseResult]] internal slot. + b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, + «rejectReaction, reason»). + + 25.4.2.1 PromiseReactionJob + [...] + 7. If handlerResult is an abrupt completion, then + a. Let status be Call(promiseCapability.[[Reject]], undefined, + «handlerResult.[[value]]»). + b. NextJob Completion(status). + 8. Let status be Call(promiseCapability.[[Resolve]], undefined, + «handlerResult.[[value]]»). + 9. NextJob Completion(status). +flags: [async] +---*/ + +var value = {}; +var p1 = new Promise(function(_, reject) { + reject(); +}); +var p2; + +p2 = p1.then(function() {}, function() { + return value; +}); + +p2.then(function(x) { + if (x !== value) { + $DONE('The `onFulfilled` handler should be invoked with the promise result.'); + return; + } + + $DONE(); +}, function() { + $DONE('The `onRejected` handler should not be invoked.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js new file mode 100644 index 0000000000..6961da914e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise reaction jobs have predictable environment +es6id: S25.4.2.1_A2.1_T1 +author: Sam Mikes +description: argument thrown through "Thrower" +flags: [async] +---*/ + +var obj = {}; + +var p = Promise.reject(obj).then( /*Identity, Thrower*/ ) + .then(function() { + $DONE("Unexpected fulfillment - promise should reject."); + }, function(arg) { + if (arg !== obj) { + $DONE("Expected reject reason to be obj, actually " + arg); + return; + } + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js new file mode 100644 index 0000000000..fadedf1e24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js @@ -0,0 +1,12 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race is callable +es6id: S25.4.4.3_A1.1_T1 +author: Sam Mikes +description: Promise.race is callable +---*/ +assert.sameValue(typeof Promise.race, "function", 'The value of `typeof Promise.race` is expected to be "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js new file mode 100644 index 0000000000..0200158ab5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js @@ -0,0 +1,15 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race returns a new promise +es6id: S25.4.4.3_A2.1_T1 +author: Sam Mikes +description: Promise.race returns a new promise +---*/ + +var p = Promise.race([]); + +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js new file mode 100644 index 0000000000..1adfb40d63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js @@ -0,0 +1,19 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race rejects on non-iterable argument +es6id: S25.4.4.3_A2.2_T1 +author: Sam Mikes +description: Promise.race rejects if argument is not object or is non-iterable +flags: [async] +---*/ + +var nonIterable = 3; + +Promise.race(nonIterable).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(nonIterable) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js new file mode 100644 index 0000000000..3555d007f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js @@ -0,0 +1,17 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: Promise.race rejects on non-iterable argument +es6id: S25.4.4.3_A2.2_T2 +author: Sam Mikes +description: Promise.race rejects if argument is not object or is non-iterable +flags: [async] +---*/ + +Promise.race(new Error("abrupt")).then(function() { + throw new Test262Error('Promise unexpectedly resolved: Promise.race(abruptCompletion) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js new file mode 100644 index 0000000000..7e8f21d0da --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js @@ -0,0 +1,28 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race rejects when GetIterator() returns an abrupt completion + 4. Let iterator be GetIterator(iterable). + 5. IfAbruptRejectPromise(iterator, promiseCapability) +es6id: S25.4.4.3_A2.2_T3 +author: Sam Mikes +description: Promise.race rejects if GetIterator throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +Object.defineProperty(iterThrows, Symbol.iterator, { + get: function() { + throw new Error("abrupt completion"); + } +}); + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw'); +}, function(err) { + assert(!!(err instanceof Error), 'The value of !!(err instanceof Error) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js new file mode 100644 index 0000000000..8e01562462 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T1.js @@ -0,0 +1,20 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race throws on invalid 'this' + Note: must have at least one element in array, or else Promise.race + never exercises the code that throws +es6id: S25.4.4.3_A3.1_T1 +author: Sam Mikes +description: Promise.race throws if 'this' does not conform to Promise constructor +---*/ + +function ZeroArgConstructor() {} + +assert.throws(TypeError, function() { + Promise.race.call(ZeroArgConstructor, [3]); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js new file mode 100644 index 0000000000..ac83127e8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A3.1_T2.js @@ -0,0 +1,22 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.race must throw TypeError per + CreatePromiseCapabilityRecord step 8 when + promiseCapabliity.[[Resolve]] is not callable +es6id: S25.4.4.3_A3.1_T2 +author: Sam Mikes +description: Promise.race throws TypeError, even on empty array, when 'this' does not conform to Promise constructor +---*/ + +function BadPromiseConstructor(f) { + f(undefined, undefined); +} + +assert.throws(TypeError, function() { + Promise.race.call(BadPromiseConstructor, []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js new file mode 100644 index 0000000000..e4602242f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A4.1_T1 +author: Sam Mikes +description: Promise.race rejects if IteratorStep throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +var error = new Test262Error(); +iterThrows[Symbol.iterator] = function() { + return { + next: function() { + throw error; + } + }; +}; + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); +}, function(reason) { + assert.sameValue(reason, error, 'The value of reason is expected to equal the value of error'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js new file mode 100644 index 0000000000..c8aeb4602f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A4.1_T2 +author: Sam Mikes +description: Promise.race rejects if IteratorStep throws +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterThrows = {}; +Object.defineProperty(iterThrows, Symbol.iterator, { + get: function() { + return { + next: function() { + var v = {}; + Object.defineProperty(v, 'value', { + get: function() { + throw new Error("abrupt completion"); + } + }); + return v; + } + }; + } +}); + +Promise.race(iterThrows).then(function() { + throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js new file mode 100644 index 0000000000..e8dfc87992 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A5.1_T1.js @@ -0,0 +1,22 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A5.1_T1 +author: Sam Mikes +description: Promise.race([]) never settles +flags: [async] +---*/ + +var p = Promise.race([]); + +p.then(function() { + throw new Test262Error("Never settles."); +}, function() { + throw new Test262Error("Never settles."); +}).then($DONE, $DONE); + +// use three 'then's to allow above to settle +// if this is a buggy Promise.race implementation +Promise.resolve().then().then().then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js new file mode 100644 index 0000000000..27dd872a3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A6.1_T1 +author: Sam Mikes +description: Promise.race([1]) settles immediately +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p = Promise.race([1]); + +sequence.push(1); + +p.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js new file mode 100644 index 0000000000..5be746bfab --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A6.2_T1 +author: Sam Mikes +description: Promise.race([p1]) settles immediately +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.reject(1), + p = Promise.race([p1]); + +sequence.push(1); + +p.then(function() { + throw new Test262Error("Should not fulfill."); +}, function() { + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); +checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js new file mode 100644 index 0000000000..768f25c842 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.resolve(1), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js new file mode 100644 index 0000000000..72b7200f85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T2 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.resolve(1), + p2 = new Promise(function() {}), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js new file mode 100644 index 0000000000..ce763b023a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.1_T3 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = new Promise(function() {}), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js new file mode 100644 index 0000000000..b38ba8eae6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.2_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var p1 = Promise.reject(1), + p2 = Promise.resolve(2), + p = Promise.race([p1, p2]); + +sequence.push(1); + +p.then(function() { + throw new Test262Error("Should not be fulfilled - expected rejection."); +}, function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); + + sequence.push(4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); + checkSequence(sequence, "This happens second"); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); + checkSequence(sequence, "This happens first"); +}).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); + checkSequence(sequence, "This happens third"); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js new file mode 100644 index 0000000000..303441a11d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.3_T1 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +flags: [async] +---*/ + +var resolveP1, rejectP2, + p1 = new Promise(function(resolve) { + resolveP1 = resolve; + }), + p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; + }); + +rejectP2(new Error("Promise.race should not see this if P1 already resolved")); +resolveP1(1); + +Promise.race([p1, p2]).then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js new file mode 100644 index 0000000000..7081e0b3f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.3_A7.3_T2 +author: Sam Mikes +description: Promise.race([p1, p2]) settles when first settles +flags: [async] +---*/ + +var resolveP1, rejectP2, + p1 = new Promise(function(resolve) { + resolveP1 = resolve; + }), + p2 = new Promise(function(resolve, reject) { + rejectP2 = reject; + }); + +Promise.race([p1, p2]).then(function() { + throw new Test262Error("Should not be fulfilled: expected rejection."); +}, function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); +}).then($DONE, $DONE); + +rejectP2(2); +resolveP1(1); diff --git a/js/src/tests/test262/built-ins/Promise/race/browser.js b/js/src/tests/test262/built-ins/Promise/race/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js new file mode 100644 index 0000000000..47dc31e96d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/capability-executor-called-twice.js @@ -0,0 +1,101 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3 +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.race ( iterable ) + + ... + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + ... + + 25.4.1.5.1 GetCapabilitiesExecutor Functions + ... + 3. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception. + 4. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception. + 5. Set promiseCapability.[[Resolve]] to resolve. + 6. Set promiseCapability.[[Reject]] to reject. + ... +---*/ + +var checkPoint = ""; +function fn1(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn1.resolve = function() { + throw new Test262Error(); +}; +Promise.race.call(fn1 , []); +assert.sameValue(checkPoint, "abc", "executor initially called with no arguments"); + +checkPoint = ""; +function fn2(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +fn2.resolve = function() { + throw new Test262Error(); +}; +Promise.race.call(fn2 , []); +assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)"); + +checkPoint = ""; +function fn3(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn3, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn3 , []); +}, "executor initially called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)"); + +checkPoint = ""; +function fn4(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn4, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn4 , []); +}, "executor initially called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)"); + +checkPoint = ""; +function fn5(executor) { + checkPoint += "a"; + executor("invalid value", 123); + checkPoint += "b"; + executor(function() {}, function() {}); + checkPoint += "c"; +} +Object.defineProperty(fn5, "resolve", { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.race.call(fn5 , []); +}, "executor initially called with (String, Number)"); +assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js new file mode 100644 index 0000000000..d5e5bc4783 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/capability-executor-not-callable.js @@ -0,0 +1,85 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3 +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.race ( iterable ) + + ... + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + ... + + 25.4.1.5 NewPromiseCapability ( C ) + ... + 4. Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1). + 5. Set the [[Capability]] internal slot of executor to promiseCapability. + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). + 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception. + 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception. + ... +---*/ + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + }, []); +}, "executor not called at all"); +assert.sameValue(checkPoint, "a", "executor not called at all"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(); + checkPoint += "b"; + }, []); +}, "executor called with no arguments"); +assert.sameValue(checkPoint, "ab", "executor called with no arguments"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(undefined, undefined); + checkPoint += "b"; + }, []); +}, "executor called with (undefined, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(undefined, function() {}); + checkPoint += "b"; + }, []); +}, "executor called with (undefined, function)"); +assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(function() {}, undefined); + checkPoint += "b"; + }, []); +}, "executor called with (function, undefined)"); +assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)"); + +var checkPoint = ""; +assert.throws(TypeError, function() { + Promise.race.call(function(executor) { + checkPoint += "a"; + executor(123, "invalid value"); + checkPoint += "b"; + }, []); +}, "executor called with (Number, String)"); +assert.sameValue(checkPoint, "ab", "executor called with (Number, String)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js new file mode 100644 index 0000000000..81988b5dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a constructor value that throws an error +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.race.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js new file mode 100644 index 0000000000..105b3fba4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-ctor.js @@ -0,0 +1,39 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a constructor value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 10. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + 13. Return Completion(result). +features: [class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.race.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js new file mode 100644 index 0000000000..5b6b4d7af4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a non-constructor value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + 7. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +---*/ + +assert.throws(TypeError, function() { + Promise.race.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js new file mode 100644 index 0000000000..c2dd20aa00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.race` invoked on a non-object value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.race.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.race.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js new file mode 100644 index 0000000000..a152a8b46c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-close.js @@ -0,0 +1,51 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error from `Promise.resolve` +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +features: [Symbol.iterator] +---*/ + +var iterDoneSpy = {}; +var returnCount = 0; +iterDoneSpy[Symbol.iterator] = function() { + return { + next: function() { + return { + value: null, + done: false + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.resolve = function() { + throw err; +}; + +Promise.race(iterDoneSpy); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..00a17b0568 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-error-reject.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error from `Promise.resolve` +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +flags: [async] +---*/ + +var err = new Test262Error(); +var CustomPromise = function(executor) { + return new Promise(executor); +}; + +CustomPromise.resolve = function() { + throw err; +}; + +Promise.race.call(CustomPromise, [1]) + .then(function() { + throw new Test262Error('The promise should be rejected.'); + }, function(reason) { + assert.sameValue(reason, err); + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..d5cb474730 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (promise rejection) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + i. ReturnIfAbrupt(nextPromise). +flags: [async] +---*/ + +var error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get: function() { + throw error; + } +}); + +Promise.race([new Promise(function() {})]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js new file mode 100644 index 0000000000..8c0b8224f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.race ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.race(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..38a700ed21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.race +info: | + Runtime Semantics: PerformPromiseRace + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var p1 = Promise.resolve(1); +var p2 = Promise.resolve(1); +var p3 = Promise.reject(1); +var p4 = Promise.resolve(1); +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.race([p1, p2, p3, p4]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 4, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..43e6718a67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.race +info: | + Runtime Semantics: PerformPromiseRace + + 1. Let promiseResolve be ? Get(constructor, `"resolve"`). + 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + ... + 1. Repeat, + ... + 1. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +---*/ + +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.race([]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 0, '`resolve` not called for empty iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..a84e88a5fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..1f5857c182 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1, 1, 1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..137367bef1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.race(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every item in iterable arg'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js new file mode 100644 index 0000000000..87f3f16312 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve-return.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +es6id: 25.4.4.1 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + [...] +---*/ + +var originalCallCount = 0; +var newCallCount = 0; +var P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +var originalThenable = { + then: function() { + originalCallCount += 1; + } +}; +var newThenable = { + then: function() { + newCallCount += 1; + } +}; + +Promise.race.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js new file mode 100644 index 0000000000..8ffdf6efae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-resolve.js @@ -0,0 +1,53 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +es6id: 25.4.4.3 +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + h. Let nextPromise be Invoke(C, "resolve", «nextValue»). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var resolve = Promise.resolve; +var callCount = 0; +var current = p1; +var next = p2; +var afterNext = p3; + +Promise.resolve = function(nextValue) { + assert.sameValue( + nextValue, current, '`resolve` invoked with next iterated value' + ); + assert.sameValue( + arguments.length, 1, '`resolve` invoked with a single argument' + ); + assert.sameValue(this, Promise, '`this` value set to the constructor'); + + current = next; + next = afterNext; + afterNext = null; + + callCount += 1; + + return resolve.apply(Promise, arguments); +}; + +Promise.race([p1, p2, p3]); + +assert.sameValue( + callCount, 3, '`resolve` invoked once for each iterated value' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js new file mode 100644 index 0000000000..b6d7e9f67c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-close.js @@ -0,0 +1,52 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var iter = {}; +var returnCount = 0; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; +promise.then = function() { + throw new Test262Error(); +}; + +Promise.race(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js new file mode 100644 index 0000000000..2b391dd34e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-error-reject.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +promise.then = function() { + throw error; +}; + +Promise.race([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js new file mode 100644 index 0000000000..e67faa28cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-close.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (closing iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +features: [Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var iter = {}; +var returnCount = 0; +iter[Symbol.iterator] = function() { + return { + next: function() { + return { + done: false, + value: promise + }; + }, + return: function() { + returnCount += 1; + return {}; + } + }; +}; +Object.defineProperty(promise, 'then', { + get: function() { + throw new Test262Error(); + } +}); + +Promise.race(iter); + +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..2c97adee85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then-get-error-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +flags: [async] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +Object.defineProperty(promise, 'then', { + get: function() { + throw error; + } +}); + +Promise.race([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/invoke-then.js b/js/src/tests/test262/built-ins/Promise/race/invoke-then.js new file mode 100644 index 0000000000..3f1ecab814 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/invoke-then.js @@ -0,0 +1,57 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +es6id: 25.4.4.3 +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + k. ReturnIfAbrupt(result). +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var callCount = 0; +var currentThis = p1; +var nextThis = p2; +var afterNextThis = p3; + +p1.then = p2.then = p3.then = function(a, b) { + assert.sameValue(typeof a, 'function', 'type of first argument'); + assert.sameValue( + a.length, + 1, + 'ES6 25.4.1.3.2: The length property of a promise resolve function is 1.' + ); + assert.sameValue(typeof b, 'function', 'type of second argument'); + assert.sameValue( + b.length, + 1, + 'ES6 25.4.1.3.1: The length property of a promise reject function is 1.' + ); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + assert.sameValue(this, currentThis, '`this` value'); + + currentThis = nextThis; + nextThis = afterNextThis; + afterNextThis = null; + + callCount += 1; +}; + +Promise.race([p1, p2, p3]); + +assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..666fbeead7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-false-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `false` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..c34066d33c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-null-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `null` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..9c077ee83a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-number-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..acf600e838 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-string-resolve.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolve when argument is a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race("a").then(function(v) { + assert.sameValue(v, "a"); + }, function() { + $DONE('The promise should be resolved, but was rejected'); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..86dee03495 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-symbol-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..1f85fed248 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-true-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `true` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..b14a91acf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-arg-is-undefined-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument is `undefined` +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js new file mode 100644 index 0000000000..b7342a76b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-false-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js new file mode 100644 index 0000000000..742970a8a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-null-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js new file mode 100644 index 0000000000..4c471a6d55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-number-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js new file mode 100644 index 0000000000..f35bb7abf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-string-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: "" + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..e5bb702110 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-symbol-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js new file mode 100644 index 0000000000..d633aba403 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-true-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..dbefa628a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-assigned-undefined-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..74adaa02ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-no-close.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +---*/ + +var iterNextValThrows = {}; +var returnCount = 0; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + }, + return: function() { + returnCount += 1; + } + }; +}; + +Promise.race(iterNextValThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js new file mode 100644 index 0000000000..866d9af062 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-next-val-err-reject.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when accessing an iterator result's `value` property (rejecting + promise) +esid: sec-promise.race +info: | + 11. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). + 12. If result is an abrupt completion, + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + + 1. Repeat + [...] + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to + true. + g. ReturnIfAbrupt(nextValue). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get: function() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedVal; + } + }; +}; + +Promise.race(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js new file mode 100644 index 0000000000..06d9baa284 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-false-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return false; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js new file mode 100644 index 0000000000..4e450e961d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-null-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return null; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js new file mode 100644 index 0000000000..2c5db3d16d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-number-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return 1; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js new file mode 100644 index 0000000000..10e860ba82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-string-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return ""; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..d1493510ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-symbol-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns a symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return Symbol(); + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js new file mode 100644 index 0000000000..0be813db4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-true-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return true; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..1a8e034a33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-returns-undefined-reject.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.race({ + [Symbol.iterator]() { + return undefined; + } + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js new file mode 100644 index 0000000000..624fc107e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-no-close.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error when advancing the provided iterable (not closing iterator) +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var returnCount = 0; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + throw new Test262Error('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + }, + return: function() { + returnCount += 1; + } + }; +}; + +Promise.race(iterStepThrows); + +assert.sameValue(returnCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js new file mode 100644 index 0000000000..3b3a3e35a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/iter-step-err-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error when advancing the provided iterable (rejecting promise) +esid: sec-promise.race +info: | + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + 12. If result is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, let result be + IteratorClose(iterator,result). + b. IfAbruptRejectPromise(result, promiseCapability). + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Symbol.iterator] +flags: [async] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get: function() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get: function() { + throw new Test262Error('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + } + }; +}; + +Promise.race(iterStepThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/length.js b/js/src/tests/test262/built-ins/Promise/race/length.js new file mode 100644 index 0000000000..0fa1f53d8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.3 +description: Promise.race `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.race.length, 1); + +verifyNotEnumerable(Promise.race, 'length'); +verifyNotWritable(Promise.race, 'length'); +verifyConfigurable(Promise.race, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/name.js b/js/src/tests/test262/built-ins/Promise/race/name.js new file mode 100644 index 0000000000..e88d3384ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.3 +description: Promise.race `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.race.name, 'race'); + +verifyNotEnumerable(Promise.race, 'name'); +verifyNotWritable(Promise.race, 'name'); +verifyConfigurable(Promise.race, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js new file mode 100644 index 0000000000..a6e0f33d59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.race does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.race), false, 'isConstructor(Promise.race) must return false'); + +assert.throws(TypeError, () => { + new Promise.race([]); +}, '`new Promise.race([])` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/prop-desc.js b/js/src/tests/test262/built-ins/Promise/race/prop-desc.js new file mode 100644 index 0000000000..ff99905270 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright 2015 Jordan Harband. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: 25.4.4.3_A1.2_T1 +author: Jordan Harband +description: Promise.race property descriptor +info: | + ES6 Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'race'); +verifyWritable(Promise, 'race'); +verifyConfigurable(Promise, 'race'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js new file mode 100644 index 0000000000..4ff5cea941 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(); + }); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function() { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js new file mode 100644 index 0000000000..25601b9361 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-from-same-thenable.js @@ -0,0 +1,65 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiserace +description: > + Promise.race does not prevent resolve from being called multiple times. +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +includes: [promiseHelper.js] +---*/ + +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function reject(value) { + callCount += 1; + sequence.push(value); + } + executor(() => { + throw new Test262Error(); + }, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let pReject; + +let a = { + then(_, rejecter) { + pReject = rejecter; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to race()'); + +Promise.race.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to race()'); + +pReject(1); +pReject(2); +pReject(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js new file mode 100644 index 0000000000..9c19236a74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-deferred.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(); + }); + } +}; +var rejector = { + then: function(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(); + }); + } +}; + +Promise.race([fulfiller, rejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js new file mode 100644 index 0000000000..32404d046b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-ignored-immed.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 2. Let promise be the value of F's [[Promise]] internal slot. + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var fulfiller = { + then: function(resolve) { + resolve(); + } +}; +var rejector = { + then: function(_, reject) { + reject(); + } +}; + +Promise.race([fulfiller, rejector]) + .then(function() { + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/reject-immed.js b/js/src/tests/test262/built-ins/Promise/race/reject-immed.js new file mode 100644 index 0000000000..9e079b496e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/reject-immed.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through immediate invocation of the provided resolving function +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = { + then: function(_, reject) { + reject(); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function() { + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js new file mode 100644 index 0000000000..df4a3c4daf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-from-same-thenable.js @@ -0,0 +1,62 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiserace +description: > + Promise.race does not prevent resolve from being called multiple times. +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +includes: [promiseHelper.js] +---*/ + +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function resolve(value) { + callCount += 1; + sequence.push(value); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +let pResolve; +let a = { + then(resolver, rejector) { + pResolve = resolver; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to race()'); + +Promise.race.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to race()'); + +pResolve(1); +pResolve(2); +pResolve(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..6640930c46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +features: [arrow-function] +includes: [promiseHelper.js] +---*/ + +let sequence = [1]; +let lateRejector = { + then(resolve, reject) { + return new Promise((resolve) => { + sequence.push(3); + resolve(); + sequence.push(4); + }).then(() => { + sequence.push(5); + resolve(9); + sequence.push(6); + reject(); + sequence.push(7); + }); + } +}; +sequence.push(2); + +Promise.race([lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 9); + assert.sameValue(sequence.length, 7); + checkSequence(sequence); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..c981b0e04e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-ignores-late-rejection.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.race +info: | + Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). + + PerformPromiseRace + + Repeat + ... + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +features: [arrow-function] +---*/ + +let resolver = { + then(resolve) { + resolve(42); + } +}; +let lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.race([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js new file mode 100644 index 0000000000..b47413a78c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.race ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.race(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js new file mode 100644 index 0000000000..1cee83de79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-obj.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var thenable = { + then: function(resolve) { + resolve(23); + } +}; + +Promise.race([thenable]) + .then(function(value) { + if (value !== 23) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js new file mode 100644 index 0000000000..4fd8820f2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-non-thenable.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var value = {}; +var thenable = { + then: function(resolve) { + resolve(value); + } +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js new file mode 100644 index 0000000000..d31b42eacc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-poisoned-then.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var thenable = { + then: function(resolve) { + resolve(poisonedThen); + } +}; + +Promise.race([thenable]) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the correct value.'); + return; + } + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js new file mode 100644 index 0000000000..a31f9b2133 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-prms-cstm-then.js @@ -0,0 +1,56 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenableValue = { + then: function(resolve) { + resolve(value); + } +}; +var thenable = new Promise(function(resolve) { + resolve(); +}); + +thenable.then = function(resolve) { + resolve(thenableValue); +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-self.js b/js/src/tests/test262/built-ins/Promise/race/resolve-self.js new file mode 100644 index 0000000000..13da6da562 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-self.js @@ -0,0 +1,59 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var self, resolve; +var builtinResolve = Promise.resolve; +var thenable = { + then: function(r) { + resolve = r; + } +}; + +try { + Promise.resolve = function(v) { + return v; + }; + self = Promise.race([thenable]); +} finally { + Promise.resolve = builtinResolve; +} + +resolve(self); + +self.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(value) { + if (!value) { + $DONE('The promise should be rejected with a value.'); + return; + } + if (value.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js b/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js new file mode 100644 index 0000000000..72a91dc07f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolve-thenable.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +es6id: 25.4.4.3 +info: | + [...] + 6. Let promiseCapability be NewPromiseCapability(C). + [...] + 11. Let result be PerformPromiseRace(iteratorRecord, promiseCapability, C). + [...] + + 25.4.4.3.1 Runtime Semantics: PerformPromiseRace + 1. Repeat + [...] + j. Let result be Invoke(nextPromise, "then", + «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenableValue = { + then: function(resolve) { + resolve(value); + } +}; +var thenable = { + then: function(resolve) { + resolve(thenableValue); + } +}; + +Promise.race([thenable]) + .then(function(val) { + if (val !== value) { + $DONE('The promise should be resolved with the correct value.'); + return; + } + $DONE(); + }, function() { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..6336fa8900 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-extra-ticks.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [promiseHelper.js] +---*/ + +let a = new Promise(resolve => resolve({})); +let sequence = [1]; +Promise.all([ + Promise.race([a]).then(resolved => { + sequence.push(4); + }), + a.then(() => { + sequence.push(3); + }).then(() => { + sequence.push(5); + }), +]).then(() => { + assert.sameValue(sequence.length, 5); + checkSequence(sequence); +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js new file mode 100644 index 0000000000..0c96494897 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-mixed.js @@ -0,0 +1,49 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [promiseHelper.js] +---*/ + +let a = Promise.reject(''); +let b = new Promise(resolve => resolve('')); +let c = new Promise((_, reject) => reject('')); +let sequence = [1]; +Promise.all([ + a.catch(() => { + sequence.push(3); + }), + Promise.race([a, b, c]).then(() => { + // This should not be present when the final + // sequence is evaluated. + sequence.push(5); + }), + b.then(() => { + sequence.push(4); + }), +]).catch(() => { + assert.sameValue(sequence.length, 4); + checkSequence(sequence); +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..882684d04f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [compareArray.js,promiseHelper.js] +---*/ + +let a = new Promise((_, reject) => reject('a')); +let b = new Promise((_, reject) => reject('b')); +let sequence = [1]; +Promise.all([ + a.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + return checkSequence(sequence, 'Expected to be called first.'); + }), + Promise.race([a, b]).catch(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + return checkSequence(sequence, 'Expected to be called third.'); + }), + b.catch(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + return checkSequence(sequence, 'Expected to be called second.'); + }) +]).then(result => { + assert.compareArray(result, [true, true, true]); + assert.sameValue(sequence.length, 5); + checkSequence(sequence); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js new file mode 100644 index 0000000000..316db984bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: Resolution ticks are set in a predictable sequence +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +includes: [compareArray.js,promiseHelper.js] +---*/ + +let a = new Promise(resolve => resolve('a')); +let b = new Promise(resolve => resolve('b')); +let sequence = [1]; +Promise.all([ + a.then(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + return checkSequence(sequence, 'Expected to be called first.'); + }), + Promise.race([a, b]).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + return checkSequence(sequence, 'Expected to be called third.'); + }), + b.then(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + return checkSequence(sequence, 'Expected to be called second.'); + }) +]).then(result => { + assert.compareArray(result, [true, true, true]); + assert.sameValue(sequence.length, 5); + checkSequence(sequence) +}).then($DONE, $DONE); +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js b/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js new file mode 100644 index 0000000000..5423f9a653 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-then-catch-finally.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.race +description: > + Resolution the first resolved promise +info: | + PerformPromiseRace + + Repeat, + Let next be IteratorStep(iteratorRecord). + If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(next). + If next is false, then + Set iteratorRecord.[[Done]] to true. + Return resultCapability.[[Promise]]. + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). + +flags: [async] +---*/ + +let a = Promise.reject('a').catch((v) => v); +let b = Promise.resolve('b').then((v) => { throw v }); +let c = Promise.reject('c').then((v) => { throw v; }); +let d = Promise.resolve('d').finally((v) => v); +let e = Promise.reject('e').finally((v) => v); +let f = Promise.resolve('f').finally((v) => { throw v; }); +let g = Promise.reject('g').finally((v) => { throw v; }); +let h = Promise.reject('h').then((v) => v, () => 'j'); +let i = Promise.resolve('i').then(v => v); + +Promise.race([a, b, c, d, e, f, g, h, i]).then(winner => { + assert.sameValue(winner, 'a'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js b/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js new file mode 100644 index 0000000000..a19c469ffc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/same-reject-function.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3.1 +description: > + Each Promise.race element is called with the same reject function. +info: | + Runtime Semantics: PerformPromiseRace ( iteratorRecord, promiseCapability, C ) + + ... + j. Let result be Invoke(nextPromise, "then", «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + ... +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(Test262Error.thrower, rejectFunction); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; + +var p1 = { + then: function(onFulfilled, onRejected) { + callCount1 += 1; + assert.sameValue(onRejected, rejectFunction, "p1.then"); + } +}; +var p2 = { + then: function(onFulfilled, onRejected) { + callCount2 += 1; + assert.sameValue(onRejected, rejectFunction, "p2.then"); + } +}; + +Promise.race.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, "p1.then call count"); +assert.sameValue(callCount2, 1, "p2.then call count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js b/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js new file mode 100644 index 0000000000..92c3cb5466 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/same-resolve-function.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.3.1 +description: > + Each Promise.race element is called with the same resolve function. +info: | + Runtime Semantics: PerformPromiseRace ( iteratorRecord, promiseCapability, C ) + + ... + j. Let result be Invoke(nextPromise, "then", «promiseCapability.[[Resolve]], promiseCapability.[[Reject]]»). + ... +---*/ + +function resolveFunction() {} + +function Constructor(executor) { + executor(resolveFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; + +var p1 = { + then: function(onFulfilled, onRejected) { + callCount1 += 1; + assert.sameValue(onFulfilled, resolveFunction, "p1.then"); + } +}; +var p2 = { + then: function(onFulfilled, onRejected) { + callCount2 += 1; + assert.sameValue(onFulfilled, resolveFunction, "p2.then"); + } +}; + +Promise.race.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, "p1.then call count"); +assert.sameValue(callCount2, 1, "p2.then call count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/shell.js b/js/src/tests/test262/built-ins/Promise/race/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/race/species-get-error.js b/js/src/tests/test262/built-ins/Promise/race/species-get-error.js new file mode 100644 index 0000000000..1198715f8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/race/species-get-error.js @@ -0,0 +1,30 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.race() does not retrieve `Symbol.species` property of the `this` value +es6id: 25.4.4.3 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... +features: [Symbol.species] +---*/ + +function C(executor) { + executor(function() {}, function() {}); +} +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error("Getter for Symbol.species called"); + } +}); +C.resolve = function() { + throw new Test262Error(); +}; + +Promise.race.call(C, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-extensible.js b/js/src/tests/test262/built-ins/Promise/reject-function-extensible.js new file mode 100644 index 0000000000..e53994dc0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-extensible.js @@ -0,0 +1,20 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.1 +description: The [[Extensible]] slot of Promise Reject functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +---*/ + +var rejectFunction; +new Promise(function(resolve, reject) { + rejectFunction = reject; +}); + +assert(Object.isExtensible(rejectFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-length.js b/js/src/tests/test262/built-ins/Promise/reject-function-length.js new file mode 100644 index 0000000000..76bcb1f5c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-length.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.1 +description: The `length` property of Promise Reject functions +info: | + The length property of a promise reject function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var rejectFunction; +new Promise(function(resolve, reject) { + rejectFunction = reject; +}); + +assert.sameValue(rejectFunction.length, 1); + +verifyNotEnumerable(rejectFunction, "length"); +verifyNotWritable(rejectFunction, "length"); +verifyConfigurable(rejectFunction, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-name.js b/js/src/tests/test262/built-ins/Promise/reject-function-name.js new file mode 100644 index 0000000000..98953b1002 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise-reject-functions +description: The `name` property of Promise Reject functions +info: | + A promise reject function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var rejectFunction; +new Promise(function(resolve, reject) { + rejectFunction = reject; +}); + +verifyProperty(rejectFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/reject-function-nonconstructor.js new file mode 100644 index 0000000000..d059d188ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-nonconstructor.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.1.3.1 +description: Promise Reject functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +---*/ + +var rejectFunction; +new Promise(function(resolve, reject) { + rejectFunction = reject; +}); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectFunction, "prototype"), false); +assert.throws(TypeError, function() { + new rejectFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-property-order.js b/js/src/tests/test262/built-ins/Promise/reject-function-property-order.js new file mode 100644 index 0000000000..7d49568d3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-property-order.js @@ -0,0 +1,22 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise reject function property order +info: | + Set order: "length", "name" +---*/ + +var rejectFunction; +new Promise(function(_, reject) { + rejectFunction = reject; +}); + +var propNames = Object.getOwnPropertyNames(rejectFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-function-prototype.js b/js/src/tests/test262/built-ins/Promise/reject-function-prototype.js new file mode 100644 index 0000000000..13dc4d919a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-function-prototype.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.1 +description: The [[Prototype]] of Promise Reject functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +---*/ + +var rejectFunction; +new Promise(function(resolve, reject) { + rejectFunction = reject; +}); + +assert.sameValue(Object.getPrototypeOf(rejectFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject-ignored-via-abrupt.js b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-abrupt.js new file mode 100644 index 0000000000..0e5a32edd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-abrupt.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolved promises ignore rejections through an abrupt completion +es6id: 25.4.3.1 +info: | + [...] + 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). + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var thenable = new Promise(function() {}); +var p = new Promise(function(resolve) { + resolve(); + throw thenable; +}); + +p.then(function() { + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-deferred.js b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-deferred.js new file mode 100644 index 0000000000..efe653f1db --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +es6id: 25.4.3.1 +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var returnValue = null; +var thenable = new Promise(function() {}); +var resolve, reject; +var p = new Promise(function(_resolve, _reject) { + resolve = _resolve; + reject = _reject; +}); + +p.then(function() { + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +resolve(); +returnValue = reject(thenable); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); diff --git a/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-immed.js b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-immed.js new file mode 100644 index 0000000000..8121fc1fe8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-ignored-via-fn-immed.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +es6id: 25.4.3.1 +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 3. Let alreadyResolved be the value of F's [[AlreadyResolved]] internal + slot. + 4. If alreadyResolved.[[value]] is true, return undefined. +flags: [async] +---*/ + +var returnValue = null; +var thenable = new Promise(function() {}); +var p = new Promise(function(resolve, reject) { + resolve(); + returnValue = reject(thenable); +}); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); + +p.then(function() { + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-abrupt-queue.js b/js/src/tests/test262/built-ins/Promise/reject-via-abrupt-queue.js new file mode 100644 index 0000000000..c0a62adeb1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-abrupt-queue.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Rejecting through an abrupt completion - captured in a queued job +esid: sec-promise-executor +info: | + 25.4.3.1 Promise ( executor ) + + ... + 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], + resolvingFunctions.[[Reject]] »). + 10. If completion is an abrupt completion, then + a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »). + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + + ... + 6. Return RejectPromise(promise, reason). + + 25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability ) + + ... + 4. If IsCallable(onRejected) is false, then + a. Set onRejected to undefined. + ... + 6. Let rejectReaction be the PromiseReaction { [[Capability]]: resultCapability, + [[Type]]: "Reject", [[Handler]]: onRejected }. + ... + 9. Else, + a. Assert: The value of promise.[[PromiseState]] is "rejected". + ... + d. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, « rejectReaction, reason »). +flags: [async] +---*/ + +var thenable = Promise.resolve(); +var p = new Promise(function() { + throw thenable; +}); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}).then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-abrupt.js b/js/src/tests/test262/built-ins/Promise/reject-via-abrupt.js new file mode 100644 index 0000000000..49e6760849 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-abrupt.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through an abrupt completion +es6id: 25.4.3.1 +info: | + [...] + 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). + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = new Promise(function() {}); +var p = new Promise(function() { + throw thenable; +}); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred-queue.js b/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred-queue.js new file mode 100644 index 0000000000..d5e5af72ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred-queue.js @@ -0,0 +1,63 @@ +// |reftest| async +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Rejecting through deferred invocation of the provided resolving function, + captured in a queued job. +esid: sec-promise-executor +info: | + 25.4.3.1 Promise ( executor ) + + ... + 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], + resolvingFunctions.[[Reject]] »). + 10. If completion is an abrupt completion, then + a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »). + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + + ... + 6. Return RejectPromise(promise, reason). + + 25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability ) + + ... + 4. If IsCallable(onRejected) is false, then + a. Set onRejected to undefined. + ... + 6. Let rejectReaction be the PromiseReaction { [[Capability]]: resultCapability, + [[Type]]: "Reject", [[Handler]]: onRejected }. + 7. If promise.[[PromiseState]] is "pending", then + ... + b. Append rejectReaction as the last element of the List that is + promise.[[PromiseRejectReactions]]. + ... +flags: [async] +---*/ + +var thenable = Promise.resolve(); +var returnValue = null; +var reject; +var p = new Promise(function(_, _reject) { + reject = _reject; +}); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}).then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + + $DONE(); +}); + +returnValue = reject(thenable); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred.js b/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred.js new file mode 100644 index 0000000000..a7c0caa05c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-fn-deferred.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +es6id: 25.4.3.1 +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = new Promise(function() {}); +var returnValue = null; +var reject; +var p = new Promise(function(_, _reject) { + reject = _reject; +}); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + + $DONE(); +}); + +returnValue = reject(thenable); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed-queue.js b/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed-queue.js new file mode 100644 index 0000000000..750ba4a2f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed-queue.js @@ -0,0 +1,60 @@ +// |reftest| async +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Rejecting through immediate invocation of the provided resolving function, + captured in a queued job. +esid: sec-promise-executor +info: | + 25.4.3.1 Promise ( executor ) + + ... + 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], + resolvingFunctions.[[Reject]] »). + 10. If completion is an abrupt completion, then + a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »). + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + + ... + 6. Return RejectPromise(promise, reason). + + 25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability ) + + ... + 4. If IsCallable(onRejected) is false, then + a. Set onRejected to undefined. + ... + 6. Let rejectReaction be the PromiseReaction { [[Capability]]: resultCapability, + [[Type]]: "Reject", [[Handler]]: onRejected }. + ... + 9. Else, + a. Assert: The value of promise.[[PromiseState]] is "rejected". + ... + d. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, « rejectReaction, reason »). +flags: [async] +---*/ + +var thenable = Promise.resolve(); +var returnValue = null; +var p = new Promise(function(_, reject) { + returnValue = reject(thenable); +}); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}).then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed.js b/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed.js new file mode 100644 index 0000000000..df9740cf3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject-via-fn-immed.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through immediate invocation of the provided resolving function +es6id: 25.4.3.1 +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +flags: [async] +---*/ + +var thenable = new Promise(function() {}); +var returnValue = null; +var p = new Promise(function(_, reject) { + returnValue = reject(thenable); +}); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(x) { + if (x !== thenable) { + $DONE('The promise should be rejected with the resolution value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js new file mode 100644 index 0000000000..999e0db577 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js @@ -0,0 +1,17 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.reject +es6id: S25.4.4.4_A1.1_T1 +author: Sam Mikes +description: Promise.reject is a function +---*/ +assert.sameValue( + typeof Promise.reject, + "function", + 'The value of `typeof Promise.reject` is expected to be "function"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js new file mode 100644 index 0000000000..101f184caf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js @@ -0,0 +1,28 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + [...] + 5. Let rejectResult be Call(promiseCapability.[[Reject]], undefined, «r»). + [...] + + 25.4.1.3.1 Promise Reject Functions + [...] + 6. Return RejectPromise(promise, reason). +es6id: 25.4.4.4 +author: Sam Mikes +description: Promise.reject creates a new settled promise +flags: [async] +---*/ + +var p = Promise.reject(3); + +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); + +p.then(function() { + throw new Test262Error("Promise should not be fulfilled."); +}, function(result) { + assert.sameValue(result, 3, 'The value of result is expected to be 3'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A3.1_T1.js new file mode 100644 index 0000000000..a3dfbbea03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A3.1_T1.js @@ -0,0 +1,18 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.reject +es6id: S25.4.4.4_A3.1_T1 +author: Sam Mikes +description: Promise.reject throws TypeError for bad 'this' +---*/ + +function ZeroArgConstructor() {} + +assert.throws(TypeError, function() { + Promise.reject.call(ZeroArgConstructor, 4); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/browser.js b/js/src/tests/test262/built-ins/Promise/reject/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/reject/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/reject/capability-executor-called-twice.js new file mode 100644 index 0000000000..17a661de34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/capability-executor-called-twice.js @@ -0,0 +1,81 @@ +// 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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/reject/capability-executor-not-callable.js new file mode 100644 index 0000000000..0002838ef8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/capability-executor-not-callable.js @@ -0,0 +1,85 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/capability-invocation-error.js b/js/src/tests/test262/built-ins/Promise/reject/capability-invocation-error.js new file mode 100644 index 0000000000..2eaac3fac3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/capability-invocation-error.js @@ -0,0 +1,33 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned by "reject" capability +esid: sec-promise.reject +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be ? NewPromiseCapability(C). + 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var P = function(executor) { + return new Promise(function() { + executor( + function() {}, + function() { + throw new Test262Error(); + } + ); + }); +}; + +assert.throws(Test262Error, function() { + Promise.reject.call(P); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/capability-invocation.js b/js/src/tests/test262/built-ins/Promise/reject/capability-invocation.js new file mode 100644 index 0000000000..c263608cf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/capability-invocation.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Invocation of "reject" capability +esid: sec-promise.reject +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be ? NewPromiseCapability(C). + 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »). + [...] + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var expectedThis = (function() { + return this; +})(); +var resolveCount = 0; +var thisValue, args; +var P = function(executor) { + return new Promise(function() { + executor( + function() { + resolveCount += 1; + }, + function() { + thisValue = this; + args = arguments; + } + ); + }); +}; + +Promise.reject.call(P, 24601); + +assert.sameValue(resolveCount, 0); + +assert.sameValue(thisValue, expectedThis); +assert.sameValue(typeof args, 'object'); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], 24601); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor-throws.js new file mode 100644 index 0000000000..85be5895f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.reject` invoked on a constructor value that throws an error +es6id: 25.4.4.4 +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be NewPromiseCapability(C). + 4. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.reject.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor.js new file mode 100644 index 0000000000..7b18f71152 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/ctx-ctor.js @@ -0,0 +1,36 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.reject` invoked on a constructor value +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + [...] + 3. Let promiseCapability be NewPromiseCapability(C). + [...] + 7. Return promiseCapability.[[Promise]]. +features: [class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.reject.call(SubPromise); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/reject/ctx-non-ctor.js new file mode 100644 index 0000000000..7a2a41ce6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/ctx-non-ctor.js @@ -0,0 +1,18 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.reject` invoked on a non-constructor value +es6id: 25.4.4.4 +info: | + [...] + 3. Let promiseCapability be NewPromiseCapability(C). + 4. ReturnIfAbrupt(promiseCapability). +---*/ + +assert.throws(TypeError, function() { + Promise.reject.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/reject/ctx-non-object.js new file mode 100644 index 0000000000..16141bbd71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked on a non-object value +es6id: 25.4.4.4 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.reject.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.reject.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.reject.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.reject.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.reject.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.reject.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/length.js b/js/src/tests/test262/built-ins/Promise/reject/length.js new file mode 100644 index 0000000000..1773dfca57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.4 +description: Promise.reject `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.reject.length, 1); + +verifyNotEnumerable(Promise.reject, 'length'); +verifyNotWritable(Promise.reject, 'length'); +verifyConfigurable(Promise.reject, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/name.js b/js/src/tests/test262/built-ins/Promise/reject/name.js new file mode 100644 index 0000000000..eb0e4c630f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.4 +description: Promise.reject `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.reject.name, 'reject'); + +verifyNotEnumerable(Promise.reject, 'name'); +verifyNotWritable(Promise.reject, 'name'); +verifyConfigurable(Promise.reject, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/reject/not-a-constructor.js new file mode 100644 index 0000000000..1fa8864edb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.reject does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.reject), false, 'isConstructor(Promise.reject) must return false'); + +assert.throws(TypeError, () => { + new Promise.reject(); +}, '`new Promise.reject()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/prop-desc.js b/js/src/tests/test262/built-ins/Promise/reject/prop-desc.js new file mode 100644 index 0000000000..d93864db99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright 2015 Jordan Harband. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: 25.4.4.4_A1.2_T1 +author: Jordan Harband +description: Promise.reject property descriptor +info: | + ES6 Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'reject'); +verifyWritable(Promise, 'reject'); +verifyConfigurable(Promise, 'reject'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/shell.js b/js/src/tests/test262/built-ins/Promise/reject/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/reject/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-extensible.js b/js/src/tests/test262/built-ins/Promise/resolve-function-extensible.js new file mode 100644 index 0000000000..5014860658 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-extensible.js @@ -0,0 +1,20 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.2 +description: The [[Extensible]] slot of Promise Resolve functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +---*/ + +var resolveFunction; +new Promise(function(resolve, reject) { + resolveFunction = resolve; +}); + +assert(Object.isExtensible(resolveFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-length.js b/js/src/tests/test262/built-ins/Promise/resolve-function-length.js new file mode 100644 index 0000000000..9d6ae8ea9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-length.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.2 +description: The `length` property of Promise Resolve functions +info: | + The length property of a promise resolve function is 1. + + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var resolveFunction; +new Promise(function(resolve, reject) { + resolveFunction = resolve; +}); + +assert.sameValue(resolveFunction.length, 1); + +verifyNotEnumerable(resolveFunction, "length"); +verifyNotWritable(resolveFunction, "length"); +verifyConfigurable(resolveFunction, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-name.js b/js/src/tests/test262/built-ins/Promise/resolve-function-name.js new file mode 100644 index 0000000000..bf3189e76b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise-resolve-functions +description: The `name` property of Promise Resolve functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var resolveFunction; +new Promise(function(resolve, reject) { + resolveFunction = resolve; +}); + +verifyProperty(resolveFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/resolve-function-nonconstructor.js new file mode 100644 index 0000000000..64891fb01f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-nonconstructor.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.1.3.2 +description: Promise Resolve functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +---*/ + +var resolveFunction; +new Promise(function(resolve, reject) { + resolveFunction = resolve; +}); + +assert.sameValue(Object.prototype.hasOwnProperty.call(resolveFunction, "prototype"), false); +assert.throws(TypeError, function() { + new resolveFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-property-order.js b/js/src/tests/test262/built-ins/Promise/resolve-function-property-order.js new file mode 100644 index 0000000000..86ca8ea378 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-property-order.js @@ -0,0 +1,22 @@ +// Copyright (C) 2020 ExE Boss. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-createbuiltinfunction +description: Promise resolve function property order +info: | + Set order: "length", "name" +---*/ + +var resolveFunction; +new Promise(function(resolve) { + resolveFunction = resolve; +}); + +var propNames = Object.getOwnPropertyNames(resolveFunction); +var lengthIndex = propNames.indexOf("length"); +var nameIndex = propNames.indexOf("name"); + +assert(lengthIndex >= 0 && nameIndex === lengthIndex + 1, + "The `length` property comes before the `name` property on built-in functions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-function-prototype.js b/js/src/tests/test262/built-ins/Promise/resolve-function-prototype.js new file mode 100644 index 0000000000..c55ede000f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-function-prototype.js @@ -0,0 +1,22 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.1.3.2 +description: The [[Prototype]] of Promise Resolve functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +---*/ + +var resolveFunction; +new Promise(function(resolve, reject) { + resolveFunction = resolve; +}); + +assert.sameValue(Object.getPrototypeOf(resolveFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-deferred.js new file mode 100644 index 0000000000..45b79bfb24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Rejected promises ignore resolution after deferred invocation of the + provided reject function +esid: sec-promise-executor +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.2 Promise Resolve Functions + + [...] + 3. Let alreadyResolved be F.[[AlreadyResolved]]. + 4. If alreadyResolved.[[Value]] is true, return undefined. +flags: [async] +---*/ + +var returnValue = null; +var thenable = new Promise(function() {}); +var resolve, reject; +var p = new Promise(function(_resolve, _reject) { + resolve = _resolve; + reject = _reject; +}); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function() { + $DONE(); +}); + +reject(thenable); +returnValue = resolve(); + +assert.sameValue(returnValue, undefined, '"resolve" function return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-immed.js new file mode 100644 index 0000000000..1963941120 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-ignored-via-fn-immed.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Rejected promises ignore resolution after immediate invocation of the + provided reject function +esid: sec-promise-executor +info: | + [...] + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + 10. If completion is an abrupt completion, then + [...] + 11. Return promise. + + 25.4.1.3.2 Promise Resolve Functions + + [...] + 3. Let alreadyResolved be F.[[AlreadyResolved]]. + 4. If alreadyResolved.[[Value]] is true, return undefined. +flags: [async] +---*/ + +var returnValue = null; +var thenable = new Promise(function() {}); +var p = new Promise(function(resolve, reject) { + reject(thenable); + returnValue = resolve(); +}); + +assert.sameValue(returnValue, undefined, '"reject" function return value'); + +p.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function() { + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-non-obj-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-non-obj-deferred.js new file mode 100644 index 0000000000..4a514d378c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-non-obj-deferred.js @@ -0,0 +1,39 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a non-object value after invocation of the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var resolve; +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then(function(value) { + if (value !== 45) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +returnValue = resolve(45); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-non-obj-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-non-obj-immed.js new file mode 100644 index 0000000000..44e603d907 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-non-obj-immed.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value from within the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var promise = new Promise(function(resolve) { + returnValue = resolve(45); +}); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); + +promise.then(function(value) { + if (value !== 45) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-deferred.js new file mode 100644 index 0000000000..307f3a42f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-deferred.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a non-thenable object value after invocation of the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var nonThenable = { + then: null +}; +var resolve; +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +returnValue = resolve(nonThenable); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-immed.js new file mode 100644 index 0000000000..2705e00776 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-non-thenable-immed.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a non-thenable object value from within the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var nonThenable = { + then: null +}; +var promise = new Promise(function(resolve) { + returnValue = resolve(nonThenable); +}); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); + +promise.then(function(value) { + if (value !== nonThenable) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-deferred.js new file mode 100644 index 0000000000..996437b636 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-deferred.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with an object with a "poisoned" `then` property after invocation + of the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var resolve; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}); + +returnValue = resolve(poisonedThen); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-immed.js new file mode 100644 index 0000000000..4276ec8e3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-poisoned-then-immed.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with an object with a "poisoned" `then` property from within the + executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var promise = new Promise(function(resolve) { + returnValue = resolve(poisonedThen); +}); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-deferred.js new file mode 100644 index 0000000000..688dfb9848 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-deferred.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a resolved Promise instance whose `then` method has been + overridden after execution of the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var resolve; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +thenable.then = function(resolve) { + resolve(value); +}; + +promise.then(function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +returnValue = resolve(thenable); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-immed.js new file mode 100644 index 0000000000..85ff117268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-prms-cstm-then-immed.js @@ -0,0 +1,62 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a resolved Promise instance whose `then` method has been + overridden from within the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var lateCallCount = 0; +var thenable = new Promise(function(resolve) { + resolve(); +}); + +thenable.then = function(resolve) { + resolve(value); +}; + +var promise = new Promise(function(resolve) { + returnValue = resolve(thenable); +}); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); + +thenable.then = function() { + lateCallCount += 1; +}; + +promise.then(function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + if (lateCallCount > 0) { + $DONE('The `then` method should be executed synchronously.'); + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-self.js b/js/src/tests/test262/built-ins/Promise/resolve-self.js new file mode 100644 index 0000000000..072b40c44d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-self.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var returnValue = null; +var resolve; +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(reason) { + if (!reason) { + $DONE('The promise should be rejected with a value.'); + return; + } + + if (reason.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); +}); + +returnValue = resolve(promise); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-thenable-deferred.js b/js/src/tests/test262/built-ins/Promise/resolve-thenable-deferred.js new file mode 100644 index 0000000000..ed9dd08288 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-thenable-deferred.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a thenable object value after execution of the executor + function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var resolve; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then(function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); + +returnValue = resolve(thenable); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); diff --git a/js/src/tests/test262/built-ins/Promise/resolve-thenable-immed.js b/js/src/tests/test262/built-ins/Promise/resolve-thenable-immed.js new file mode 100644 index 0000000000..1e50d7e080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve-thenable-immed.js @@ -0,0 +1,47 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Resolving with a thenable object value from within the executor function +es6id: 25.4.3.1 +info: | + [...] + 8. Let resolvingFunctions be CreateResolvingFunctions(promise). + 9. Let completion be Call(executor, undefined, + «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»). + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var thenable = new Promise(function(resolve) { + resolve(value); +}); +var promise = new Promise(function(resolve) { + returnValue = resolve(thenable); +}); + +assert.sameValue(returnValue, undefined, '"resolve" return value'); + +promise.then(function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js new file mode 100644 index 0000000000..ba9e815a66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js @@ -0,0 +1,17 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.resolve +es6id: S25.4.4.5_A1.1_T1 +author: Sam Mikes +description: Promise.resolve is a function +---*/ +assert.sameValue( + typeof Promise.resolve, + "function", + 'The value of `typeof Promise.resolve` is expected to be "function"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js new file mode 100644 index 0000000000..4277dcbbd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js @@ -0,0 +1,15 @@ +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.5_A2.1_T1 +author: Sam Mikes +description: Promise.resolve passes through a promise w/ same Constructor +---*/ + +var p1 = Promise.resolve(1), + p2 = Promise.resolve(p1); + +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js new file mode 100644 index 0000000000..1445d3a242 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.5_A2.2_T1 +author: Sam Mikes +description: Promise.resolve passes through an unsettled promise w/ same Constructor +flags: [async] +---*/ + +var resolveP1, + p1 = new Promise(function(resolve) { + resolveP1 = resolve; + }), + p2 = Promise.resolve(p1), + arg = {}; + +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); + +p2.then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); + +resolveP1(arg); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js new file mode 100644 index 0000000000..e028c21cba --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: S25.4.4.5_A2.3_T1 +author: Sam Mikes +description: Promise.resolve passes through an unsettled promise w/ same Constructor +flags: [async] +---*/ + +var rejectP1, + p1 = new Promise(function(resolve, reject) { + rejectP1 = reject; + }), + p2 = Promise.resolve(p1), + arg = {}; + +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); + +p2.then(function() { + throw new Test262Error("Expected p2 to be rejected, not fulfilled."); +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); + +rejectP1(arg); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A3.1_T1.js new file mode 100644 index 0000000000..78b95b93a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A3.1_T1.js @@ -0,0 +1,56 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.resolve +es6id: S25.4.4.5_A3.1_T1 +author: Sam Mikes +description: Promise.resolve delegates to foreign thenable +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var thenable = { + then: function(onResolve, onReject) { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "thenable.then called"); + + assert.sameValue(this, thenable); + + onResolve('resolved'); + + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "after resolved"); + + throw new Error('interrupt flow'); + + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "duplicate sequence point not pushed"); + } +}; + +sequence.push(1); +assert.sameValue(sequence.length, 1); +checkSequence(sequence, "no async calls yet"); + +var p1 = Promise.resolve(thenable); + +sequence.push(2); +assert.sameValue(sequence.length, 2); +checkSequence(sequence, "thenable.then queued but not yet called"); + +p1.then(function(q) { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, "all done"); + + assert.sameValue(q, 'resolved'); + +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js new file mode 100644 index 0000000000..25b8acf3a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js @@ -0,0 +1,25 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Section 25.4.1.4.2 +es6id: S25.4.4.5_A3.1_T1 +author: Sam Mikes +description: self-resolved Promise throws TypeError +flags: [async] +---*/ + +var resolveP, + p = new Promise(function(resolve) { + resolveP = resolve; + }); + +resolveP(p); + +p.then(function() { + throw new Test262Error("Should not fulfill: should reject with TypeError."); +}, function(err) { + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_1.js new file mode 100644 index 0000000000..629b94b509 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_1.js @@ -0,0 +1,24 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.resolve +es6id: S25.4.4.5 +author: Sam Mikes +description: Promise.resolve delegates to foreign thenable +flags: [async] +---*/ + +var thenable = { + then: function(onResolve, onReject) { + return onResolve('resolved'); + } +}; + +var p = Promise.resolve(thenable); + +p.then(function(r) { + assert.sameValue(r, 'resolved'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_2.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_2.js new file mode 100644 index 0000000000..bc748bf8fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.Promise_resolve_foreign_thenable_2.js @@ -0,0 +1,46 @@ +// |reftest| async +// Copyright 2014 Cubane Canada, Inc. All rights reserved. +// See LICENSE for details. + +/*--- +info: | + Promise.resolve +es6id: S25.4.4.5 +author: Sam Mikes +description: Promise.resolve delegates to foreign thenable +includes: [promiseHelper.js] +flags: [async] +---*/ + +var sequence = []; + +var thenable = { + then: function(onResolve, onReject) { + + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, "thenable.then called"); + + assert.sameValue(this, thenable, "thenable.then called with `thenable` as `this`"); + + return onResolve('resolved'); + } +}; + +sequence.push(1); +assert.sameValue(sequence.length, 1); +checkSequence(sequence, "no async calls yet"); + +var p = Promise.resolve(thenable); + +sequence.push(2); +assert.sameValue(sequence.length, 2); +checkSequence(sequence, "thenable.then queued but not yet called"); + +p.then(function(r) { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, "all done"); + + assert.sameValue(r, 'resolved'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/arg-non-thenable.js b/js/src/tests/test262/built-ins/Promise/resolve/arg-non-thenable.js new file mode 100644 index 0000000000..1f941e050b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/arg-non-thenable.js @@ -0,0 +1,31 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked with an object whose `then` property is not callable +es6id: 25.4.4.5 +info: | + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + + [...] + + 25.4.1.3.2 Promise Resolve Functions + + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») + 13. Return undefined. +flags: [async] +---*/ + +var nonThenable = { + then: null +}; + +Promise.resolve(nonThenable).then(function(value) { + assert.sameValue(value, nonThenable); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/arg-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/resolve/arg-poisoned-then.js new file mode 100644 index 0000000000..6adc9372a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/arg-poisoned-then.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked with an object with a "poisoned" `then` property +es6id: 25.4.4.5 +info: | + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + + [...] + + 25.4.1.3.2 Promise Resolve Functions + + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var poisonedThen = {}; +var err = new Test262Error(); +Object.defineProperty(poisonedThen, 'then', { + get: function() { + throw err; + } +}); + +Promise.resolve(poisonedThen).then(function() { + throw new Test262Error( + 'Promise should be rejected when retrieving `then` property throws an error' + ); +}, function(reason) { + assert.sameValue(reason, err); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/arg-uniq-ctor.js b/js/src/tests/test262/built-ins/Promise/resolve/arg-uniq-ctor.js new file mode 100644 index 0000000000..d3f268f0a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/arg-uniq-ctor.js @@ -0,0 +1,29 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked with a Promise with a unique constructor +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + [...] + 3. If IsPromise(x) is true, + a. Let xConstructor be Get(x, "constructor"). + b. ReturnIfAbrupt(xConstructor). + c. If SameValue(xConstructor, C) is true, return x. + 4. Let promiseCapability be NewPromiseCapability(C). + [...] + 8. Return promiseCapability.[[Promise]]. +---*/ + +var promise1 = new Promise(function() {}); +var promise2; + +promise1.constructor = null; + +promise2 = Promise.resolve(promise1); + +assert.sameValue(promise1 === promise2, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/browser.js b/js/src/tests/test262/built-ins/Promise/resolve/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-called-twice.js new file mode 100644 index 0000000000..3a5375dd79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-called-twice.js @@ -0,0 +1,81 @@ +// 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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-not-callable.js new file mode 100644 index 0000000000..09ed28476b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/capability-executor-not-callable.js @@ -0,0 +1,85 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es6id: 25.4.4.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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/capability-invocation-error.js b/js/src/tests/test262/built-ins/Promise/resolve/capability-invocation-error.js new file mode 100644 index 0000000000..6302336b1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/capability-invocation-error.js @@ -0,0 +1,33 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned by "resolve" capability +esid: sec-promise.resolve +info: | + 1. Let C be the this value. + [...] + 4. Let promiseCapability be ? NewPromiseCapability(C). + 5. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var P = function(executor) { + return new Promise(function() { + executor( + function() { + throw new Test262Error(); + }, + function() {} + ); + }); +}; + +assert.throws(Test262Error, function() { + Promise.resolve.call(P); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/context-non-object-with-promise.js b/js/src/tests/test262/built-ins/Promise/resolve/context-non-object-with-promise.js new file mode 100644 index 0000000000..be4934f14e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/context-non-object-with-promise.js @@ -0,0 +1,50 @@ +// 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() {}); + +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor-throws.js new file mode 100644 index 0000000000..f73047169d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked on a constructor value that throws an error +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + [...] + 4. Let promiseCapability be NewPromiseCapability(C). + 5. ReturnIfAbrupt(promiseCapability). + + 25.4.1.5 NewPromiseCapability + [...] + 6. Let promise be Construct(C, «executor»). + 7. ReturnIfAbrupt(promise). +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.resolve.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor.js new file mode 100644 index 0000000000..ea39cb7559 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/ctx-ctor.js @@ -0,0 +1,36 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked on a constructor value +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + [...] + 4. Let promiseCapability be NewPromiseCapability(C). + [...] + 8. Return promiseCapability.[[Promise]]. +features: [class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.resolve.call(SubPromise); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-ctor.js new file mode 100644 index 0000000000..03bfe89783 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-ctor.js @@ -0,0 +1,18 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked on a non-constructor value +es6id: 25.4.4.5 +info: | + [...] + 4. Let promiseCapability be NewPromiseCapability(C). + 5. ReturnIfAbrupt(promiseCapability). +---*/ + +assert.throws(TypeError, function() { + Promise.resolve.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-object.js new file mode 100644 index 0000000000..9f7b8f9e7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/ctx-non-object.js @@ -0,0 +1,38 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `Promise.resolve` invoked on a non-object value +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.resolve.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.resolve.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.resolve.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.resolve.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.resolve.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.resolve.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/length.js b/js/src/tests/test262/built-ins/Promise/resolve/length.js new file mode 100644 index 0000000000..a73283a4b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.5 +description: Promise.resolve `length` property +info: | + ES6 Section 17: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this value + is equal to the largest number of named arguments shown in the subclause + headings for the function description, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.resolve.length, 1); + +verifyNotEnumerable(Promise.resolve, 'length'); +verifyNotWritable(Promise.resolve, 'length'); +verifyConfigurable(Promise.resolve, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/name.js b/js/src/tests/test262/built-ins/Promise/resolve/name.js new file mode 100644 index 0000000000..b9644562b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.4.5 +description: Promise.resolve `name` property +info: | + ES6 Section 17: + + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. Unless otherwise specified, this value is the name that is given to + the function in this specification. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Promise.resolve.name, 'resolve'); + +verifyNotEnumerable(Promise.resolve, 'name'); +verifyNotWritable(Promise.resolve, 'name'); +verifyConfigurable(Promise.resolve, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/resolve/not-a-constructor.js new file mode 100644 index 0000000000..e455743938 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.resolve does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.resolve), false, 'isConstructor(Promise.resolve) must return false'); + +assert.throws(TypeError, () => { + new Promise.resolve(); +}, '`new Promise.resolve()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/prop-desc.js b/js/src/tests/test262/built-ins/Promise/resolve/prop-desc.js new file mode 100644 index 0000000000..ecbf48f185 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright 2015 Jordan Harband. All rights reserved. +// See LICENSE for details. + +/*--- +es6id: 25.4.4.5_A1.2_T1 +author: Jordan Harband +description: Promise.resolve should be non-enumerable +info: | + ES6 Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Promise, 'resolve'); +verifyWritable(Promise, 'resolve'); +verifyConfigurable(Promise, 'resolve'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-from-promise-capability.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-from-promise-capability.js new file mode 100644 index 0000000000..910f3791e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-from-promise-capability.js @@ -0,0 +1,42 @@ +// 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 expectedThisValue = (function() { + return this; +}()); +var callCount = 0; +var object = {}; +var thisValue, args; + +Promise.resolve.call(function(executor) { + function resolve(v) { + callCount += 1; + thisValue = this; + args = arguments; + } + executor(resolve, Test262Error.thrower); + assert.sameValue(callCount, 0, "callCount before returning from constructor"); +}, object); + +assert.sameValue(callCount, 1, "callCount after call to resolve()"); +assert.sameValue(typeof args, "object"); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], object); +assert.sameValue(thisValue, expectedThisValue); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-obj.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-obj.js new file mode 100644 index 0000000000..a26ef53ca9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-obj.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-object value +es6id: 25.4.4.5 +info: | + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 7. If Type(resolution) is not Object, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +Promise.resolve(23).then(function(value) { + if (value !== 23) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-thenable.js new file mode 100644 index 0000000000..0ed1dd2541 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-non-thenable.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +es6id: 25.4.4.5 +info: | + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + a. Return FulfillPromise(promise, resolution). +flags: [async] +---*/ + +var value = {}; + +Promise.resolve(value).then(function(value) { + if (value !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-poisoned-then.js new file mode 100644 index 0000000000..330c890b42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-poisoned-then.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" then property +es6id: 25.4.4.5 +info: | + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + a. Return RejectPromise(promise, then.[[value]]). +flags: [async] +---*/ + +var value = {}; +var resolve; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); + +Promise.resolve(poisonedThen).then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the provided value.'); + return; + } + + $DONE(); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-prms-cstm-then.js new file mode 100644 index 0000000000..fe95c71f84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-prms-cstm-then.js @@ -0,0 +1,44 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a resolved Promise instance whose `then` method has been overridden +es6id: 25.4.4.5 +info: | + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +---*/ + +var value = {}; +var rejectCallCount = 0; +var thenable = new Promise(function(resolve) { + resolve(); +}); +var resolvedValue; + +thenable.then = function(resolve) { + resolve(value); +}; + +Promise.resolve(thenable).then(function(val) { + resolvedValue = val; +}, function() { + rejectCallCount += 1; +}); + +assert.sameValue(resolvedValue, value); +assert.sameValue(rejectCallCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-self.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-self.js new file mode 100644 index 0000000000..03d14879eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-self.js @@ -0,0 +1,48 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a reference to the promise itself +es6id: 25.4.4.5 +info: | + 1. Let C be the this value. + [...] + 4. Let promiseCapability be NewPromiseCapability(C). + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 6. If SameValue(resolution, promise) is true, then + a. Let selfResolutionError be a newly created TypeError object. + b. Return RejectPromise(promise, selfResolutionError). +flags: [async] +---*/ + +var resolve, reject; +var promise = new Promise(function(_resolve, _reject) { + resolve = _resolve; + reject = _reject; +}); +var P = function(executor) { + executor(resolve, reject); + return promise; +}; + +Promise.resolve.call(P, promise) + .then(function() { + $DONE('The promise should not be fulfilled.'); + }, function(value) { + if (!value) { + $DONE('The promise should be rejected with a value.'); + return; + } + if (value.constructor !== TypeError) { + $DONE('The promise should be rejected with a TypeError instance.'); + return; + } + + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/resolve-thenable.js b/js/src/tests/test262/built-ins/Promise/resolve/resolve-thenable.js new file mode 100644 index 0000000000..1934ede551 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/resolve-thenable.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +es6id: 25.4.4.5 +info: | + [...] + 6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, + «x»). + [...] + + 25.4.1.3.2 Promise Resolve Functions + [...] + 8. Let then be Get(resolution, "then"). + 9. If then is an abrupt completion, then + [...] + 10. Let thenAction be then.[[value]]. + 11. If IsCallable(thenAction) is false, then + [...] + 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, + «promise, resolution, thenAction») +flags: [async] +---*/ + +var value = {}; +var thenable = { + then: function(resolve) { + resolve(value); + } +}; + +Promise.resolve(thenable).then(function(val) { + if (val !== value) { + $DONE('The promise should be fulfilled with the provided value.'); + return; + } + + $DONE(); +}, function() { + $DONE('The promise should not be rejected.'); +}); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/shell.js b/js/src/tests/test262/built-ins/Promise/resolve/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/resolve/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/shell.js b/js/src/tests/test262/built-ins/Promise/shell.js new file mode 100644 index 0000000000..6fbf1a63a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/shell.js @@ -0,0 +1,101 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: promiseHelper.js +// Copyright (C) 2017 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Check that an array contains a numeric sequence starting at 1 + and incrementing by 1 for each entry in the array. Used by + Promise tests to assert the order of execution in deep Promise + resolution pipelines. +defines: [checkSequence, checkSettledPromises] +---*/ + +function checkSequence(arr, message) { + arr.forEach(function(e, i) { + if (e !== (i+1)) { + throw new Test262Error((message ? message : "Steps in unexpected sequence:") + + " '" + arr.join(',') + "'"); + } + }); + + return true; +} + +function checkSettledPromises(settleds, expected, message) { + const prefix = message ? `${message}: ` : ''; + + assert.sameValue(Array.isArray(settleds), true, `${prefix}Settled values is an array`); + + assert.sameValue( + settleds.length, + expected.length, + `${prefix}The settled values has a different length than expected` + ); + + settleds.forEach((settled, i) => { + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'status'), + true, + `${prefix}The settled value has a property status` + ); + + assert.sameValue(settled.status, expected[i].status, `${prefix}status for item ${i}`); + + if (settled.status === 'fulfilled') { + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'value'), + true, + `${prefix}The fulfilled promise has a property named value` + ); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'reason'), + false, + `${prefix}The fulfilled promise has no property named reason` + ); + + assert.sameValue(settled.value, expected[i].value, `${prefix}value for item ${i}`); + } else { + assert.sameValue(settled.status, 'rejected', `${prefix}Valid statuses are only fulfilled or rejected`); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'value'), + false, + `${prefix}The fulfilled promise has no property named value` + ); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'reason'), + true, + `${prefix}The fulfilled promise has a property named reason` + ); + + assert.sameValue(settled.reason, expected[i].reason, `${prefix}Reason value for item ${i}`); + } + }); +} diff --git a/js/src/tests/test262/built-ins/Promise/undefined-newtarget.js b/js/src/tests/test262/built-ins/Promise/undefined-newtarget.js new file mode 100644 index 0000000000..e672e2a63e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/undefined-newtarget.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise-executor +description: > + Throws a TypeError if Promise is called without a NewTarget. +info: | + 25.6.3.1 Promise ( executor ) + + 1. If NewTarget is undefined, throw a TypeError exception. +---*/ + +assert.throws(TypeError, function() { + Promise(function() {}); +}); + +assert.throws(TypeError, function() { + Promise.call(null, function() {}); +}); + +var p = new Promise(function() {}); +assert.throws(TypeError, function() { + Promise.call(p, function() {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/browser.js b/js/src/tests/test262/built-ins/Promise/withResolvers/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-ctor.js new file mode 100644 index 0000000000..c13c68fa9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-ctor.js @@ -0,0 +1,18 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers produces instances of the receiver +esid: sec-promise.withresolvers +features: [promise-with-resolvers] +---*/ + +class SubPromise extends Promise {} + +var instance = Promise.withResolvers.call(SubPromise); + +assert.sameValue(instance.promise.constructor, SubPromise); +assert.sameValue(instance.promise instanceof SubPromise, true); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-ctor.js new file mode 100644 index 0000000000..b5364593b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-ctor.js @@ -0,0 +1,14 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers errors when the receiver is not a constructor +esid: sec-promise.withresolvers +features: [promise-with-resolvers] +---*/ + +assert.throws(TypeError, function() { + Promise.withResolvers.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-object.js new file mode 100644 index 0000000000..3be318a003 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/ctx-non-object.js @@ -0,0 +1,34 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers errors when the receiver is not an object +esid: sec-promise.withresolvers +features: [promise-with-resolvers] +---*/ + +assert.throws(TypeError, function() { + Promise.withResolvers.call(undefined); +}); + +assert.throws(TypeError, function() { + Promise.withResolvers.call(null); +}); + +assert.throws(TypeError, function() { + Promise.withResolvers.call(86); +}); + +assert.throws(TypeError, function() { + Promise.withResolvers.call('string'); +}); + +assert.throws(TypeError, function() { + Promise.withResolvers.call(true); +}); + +assert.throws(TypeError, function() { + Promise.withResolvers.call(Symbol()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/promise.js b/js/src/tests/test262/built-ins/Promise/withResolvers/promise.js new file mode 100644 index 0000000000..7a58ecef14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/promise.js @@ -0,0 +1,17 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers return value has a property called "promise" which is a Promise +esid: sec-promise.withresolvers +features: [promise-with-resolvers] +---*/ + + +var instance = Promise.withResolvers(); + +assert.sameValue(instance.promise.constructor, Promise); +assert.sameValue(instance.promise instanceof Promise, true); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/resolvers.js b/js/src/tests/test262/built-ins/Promise/withResolvers/resolvers.js new file mode 100644 index 0000000000..8a0606870a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/resolvers.js @@ -0,0 +1,18 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers return value has properties called "resolve" and "reject" which are unary functions +esid: sec-promise.withresolvers +features: [promise-with-resolvers] +---*/ + + +var instance = Promise.withResolvers(); + +assert.sameValue(typeof instance.resolve, 'function', 'type of resolve property'); +assert.sameValue(instance.resolve.length, 1, 'length of resolve property'); +assert.sameValue(typeof instance.reject, 'function', 'type of reject property'); +assert.sameValue(instance.reject.length, 1, 'length of reject property'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/result.js b/js/src/tests/test262/built-ins/Promise/withResolvers/result.js new file mode 100644 index 0000000000..0679dfaf31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/result.js @@ -0,0 +1,36 @@ +// Copyright (C) 2023 Peter Klecha. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise.withResolvers result is an object with keys "promise", "reject", and "resolve" +esid: sec-promise.withresolvers +includes: [propertyHelper.js] +features: [promise-with-resolvers] +---*/ + + +var instance = Promise.withResolvers(); + +assert.sameValue(typeof instance, "object"); +assert.notSameValue(instance, null); +assert(instance instanceof Object); + +verifyProperty(instance, "promise", { + writable: true, + configurable: true, + enumerable: true, +}) + +verifyProperty(instance, "resolve", { + writable: true, + configurable: true, + enumerable: true, +}) + +verifyProperty(instance, "reject", { + writable: true, + configurable: true, + enumerable: true, +}) + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/withResolvers/shell.js b/js/src/tests/test262/built-ins/Promise/withResolvers/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/withResolvers/shell.js |