mirror of https://github.com/tc39/test262.git
Merge pull request #1156 from ljharb/finally
Promise.prototype.finally: add tests
This commit is contained in:
commit
e467c83aa0
|
@ -5,3 +5,9 @@
|
|||
console/TestCases
|
||||
github-deploy-key
|
||||
github-deploy-key.pub
|
||||
node_modules
|
||||
|
||||
# Only apps should have lockfiles
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
npm-shrinkwrap.json
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
#
|
||||
# https://github.com/tc39/process-document
|
||||
|
||||
# Promise.prototype.finally
|
||||
# https://github.com/tc39/proposal-promise-finally
|
||||
Promise.prototype.finally
|
||||
|
||||
# Async Iteration and Generators
|
||||
# https://github.com/tc39/proposal-async-iteration
|
||||
async-iteration
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// 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;
|
||||
|
||||
target.then = function(a, b) {
|
||||
callCount += 1;
|
||||
|
||||
thisValue = this;
|
||||
argCount = arguments.length;
|
||||
firstArg = a;
|
||||
secondArg = b;
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
var originalFinallyHandler = function () {};
|
||||
|
||||
var result = Promise.prototype.finally.call(target, originalFinallyHandler, 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(
|
||||
typeof firstArg,
|
||||
'function',
|
||||
'Invokes `then` method with a function as the first argument'
|
||||
);
|
||||
assert.notSameValue(firstArg, originalFinallyHandler, 'Invokes `then` method with a different fulfillment handler');
|
||||
assert.sameValue(
|
||||
typeof secondArg,
|
||||
'function',
|
||||
'Invokes `then` method with a function as the second argument'
|
||||
);
|
||||
assert.notSameValue(secondArg, originalFinallyHandler, 'Invokes `then` method with a different fulfillment handler');
|
||||
|
||||
assert.sameValue(result, returnValue, 'Returns the result of the invocation of `then`');
|
|
@ -0,0 +1,49 @@
|
|||
// 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`');
|
|
@ -0,0 +1,20 @@
|
|||
// 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'
|
||||
);
|
|
@ -0,0 +1,16 @@
|
|||
// 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`'
|
||||
);
|
|
@ -0,0 +1,28 @@
|
|||
// 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,
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
// 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');
|
|
@ -0,0 +1,19 @@
|
|||
// 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');
|
|
@ -0,0 +1,46 @@
|
|||
// 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]
|
||||
---*/
|
||||
|
||||
var initialThenCount = 0;
|
||||
var noReason = {};
|
||||
var no = Promise.reject(noReason);
|
||||
no.then = function () {
|
||||
initialThenCount += 1;
|
||||
return Promise.prototype.then.apply(this, arguments);
|
||||
};
|
||||
|
||||
var onFinallyThenCount = 0;
|
||||
var yesValue = {};
|
||||
var yes = Promise.resolve(yesValue);
|
||||
yes.then = function () {
|
||||
onFinallyThenCount += 1;
|
||||
return Promise.prototype.then.apply(this, arguments);
|
||||
};
|
||||
|
||||
var finallyCalled = false;
|
||||
var catchCalled = false;
|
||||
|
||||
no.catch(function (e) {
|
||||
assert.sameValue(e, noReason);
|
||||
throw e;
|
||||
}).finally(function () {
|
||||
finallyCalled = true;
|
||||
return yes;
|
||||
}).catch(function (e) {
|
||||
catchCalled = true;
|
||||
assert.sameValue(e, noReason);
|
||||
}).then(function () {
|
||||
assert.sameValue(finallyCalled, true, 'initial finally was called');
|
||||
assert.sameValue(initialThenCount, 1, 'initial finally invokes .then once');
|
||||
|
||||
assert.sameValue(catchCalled, true, 'catch was called');
|
||||
assert.sameValue(onFinallyThenCount, 1, 'onFinally return promise has .then invoked once');
|
||||
$DONE();
|
||||
}).catch($ERROR);
|
|
@ -0,0 +1,23 @@
|
|||
// 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]
|
||||
---*/
|
||||
|
||||
var original = {};
|
||||
var replacement = {};
|
||||
|
||||
var p = Promise.reject(original);
|
||||
|
||||
p.finally(function () {
|
||||
assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
|
||||
return replacement;
|
||||
}).then(function () {
|
||||
$ERROR('promise is rejected pre-finally; onFulfill should not be called');
|
||||
}).catch(function (reason) {
|
||||
assert.sameValue(reason, original, 'onFinally can not override the rejection value by returning');
|
||||
}).then($DONE).catch($ERROR);
|
23
test/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js
vendored
Normal file
23
test/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// 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]
|
||||
---*/
|
||||
|
||||
var original = {};
|
||||
var thrown = {};
|
||||
|
||||
var p = Promise.reject(original);
|
||||
|
||||
p.finally(function () {
|
||||
assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
|
||||
throw thrown;
|
||||
}).then(function () {
|
||||
$ERROR('promise is rejected; onFulfill should not be called');
|
||||
}).catch(function (reason) {
|
||||
assert.sameValue(reason, thrown, 'onFinally can override the rejection reason by throwing');
|
||||
}).then($DONE).catch($ERROR);
|
|
@ -0,0 +1,20 @@
|
|||
// 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]
|
||||
---*/
|
||||
|
||||
var obj = {};
|
||||
|
||||
var p = Promise.resolve(obj);
|
||||
|
||||
p.finally(function () {
|
||||
assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
|
||||
return {};
|
||||
}).then(function (x) {
|
||||
assert.sameValue(x, obj, 'onFinally can not override the resolution value');
|
||||
}).then($DONE).catch($ERROR);
|
|
@ -0,0 +1,46 @@
|
|||
// 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]
|
||||
---*/
|
||||
|
||||
var initialThenCount = 0;
|
||||
var yesValue = {};
|
||||
var yes = Promise.resolve(yesValue);
|
||||
yes.then = function () {
|
||||
initialThenCount += 1;
|
||||
return Promise.prototype.then.apply(this, arguments);
|
||||
};
|
||||
|
||||
var onFinallyThenCount = 0;
|
||||
var noReason = {};
|
||||
var no = Promise.reject(noReason);
|
||||
no.then = function () {
|
||||
onFinallyThenCount += 1;
|
||||
return Promise.prototype.then.apply(this, arguments);
|
||||
};
|
||||
|
||||
var finallyCalled = false;
|
||||
var catchCalled = false;
|
||||
|
||||
yes.then(function (x) {
|
||||
assert.sameValue(x, yesValue);
|
||||
return x;
|
||||
}).finally(function () {
|
||||
finallyCalled = true;
|
||||
return no;
|
||||
}).catch(function (e) {
|
||||
catchCalled = true;
|
||||
assert.sameValue(e, noReason);
|
||||
}).then(function () {
|
||||
assert.sameValue(finallyCalled, true, 'initial finally was called');
|
||||
assert.sameValue(initialThenCount, 1, 'initial finally invokes .then once');
|
||||
|
||||
assert.sameValue(catchCalled, true, 'catch was called');
|
||||
assert.sameValue(onFinallyThenCount, 1, 'onFinally return promise has .then invoked once');
|
||||
$DONE();
|
||||
}).catch($ERROR);
|
|
@ -0,0 +1,17 @@
|
|||
// 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.throws(TypeError, function() {
|
||||
Promise.prototype.finally.call(undefined);
|
||||
}, 'undefined');
|
||||
|
||||
assert.throws(TypeError, function() {
|
||||
Promise.prototype.finally.call(null);
|
||||
}, 'null');
|
|
@ -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 called with a `this` value that does not define a
|
||||
callable `then` property
|
||||
esid: sec-promise.prototype.finally
|
||||
features: [Symbol, Promise.prototype.finally]
|
||||
---*/
|
||||
|
||||
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');
|
|
@ -0,0 +1,24 @@
|
|||
// 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();
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
// 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();
|
||||
});
|
Loading…
Reference in New Issue