diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Promise/prototype')
131 files changed, 4950 insertions, 0 deletions
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 |