| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --allow-natives-syntax |
| |
| load('test/mjsunit/test-async.js'); |
| |
| assertThrows(() => Promise.prototype.finally.call(5), TypeError); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.resolve(3).finally().then(x => { |
| assert.equals(3, x); |
| }, assert.unreachable); |
| }, "resolve/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.reject(3).finally().then(assert.unreachable, x => { |
| assert.equals(3, x); |
| }); |
| }, "reject/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.resolve(3).finally(2).then(x => { |
| assert.equals(3, x); |
| }, assert.unreachable); |
| }, "resolve/finally-return-notcallable/then"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.reject(3).finally(2).then(assert.unreachable, e => { |
| assert.equals(3, e); |
| }); |
| }, "reject/finally-return-notcallable/then"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.reject(3).finally().catch(reason => { |
| assert.equals(3, reason); |
| }); |
| }, "reject/finally/catch"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| |
| Promise.reject(3).finally().then(assert.unreachable).catch(reason => { |
| assert.equals(3, reason); |
| }); |
| }, "reject/finally/then/catch"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.resolve(3) |
| .then(x => { |
| assert.equals(3, x); |
| return x; |
| }) |
| .finally() |
| .then(x => { |
| assert.equals(3, x); |
| }, assert.unreachable); |
| }, "resolve/then/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .catch(x => { |
| assert.equals(3, x); |
| return x; |
| }) |
| .finally() |
| .then(x => { |
| assert.equals(3, x); |
| }, assert.unreachable); |
| }, "reject/catch/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.resolve(3) |
| .finally(function onFinally() { |
| print("in finally"); |
| assert.equals(0, arguments.length); |
| throw 1; |
| }) |
| .then(assert.unreachable, function onRejected(reason) { |
| assert.equals(1, reason); |
| }); |
| }, "resolve/finally-throw/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| throw 1; |
| }) |
| .then(assert.unreachable, function onRejected(reason) { |
| assert.equals(1, reason); |
| }); |
| }, "reject/finally-throw/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.resolve(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return 4; |
| }) |
| .then(x => { |
| assert.equals(x, 3); |
| }, assert.unreachable); |
| }, "resolve/finally-return/then"); |
| |
| // reject/finally-return/then |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return 4; |
| }) |
| .then(assert.unreachable, x => { |
| assert.equals(x, 3); |
| }); |
| }); |
| |
| // reject/catch-throw/finally-throw/then |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.reject(3) |
| .catch(e => { |
| assert.equals(3, e); |
| throw e; |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| throw 4; |
| }) |
| .then(assert.unreachable, function onRejected(e) { |
| assert.equals(4, e); |
| }); |
| }); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.resolve(3) |
| .then(e => { |
| assert.equals(3, e); |
| throw e; |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| throw 4; |
| }) |
| .then(assert.unreachable, function onRejected(e) { |
| assert.equals(4, e); |
| }); |
| }, "resolve/then-throw/finally-throw/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.resolve(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.reject(4); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(4, e); |
| }); |
| }, "resolve/finally-return-rejected-promise/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.reject(4); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(4, e); |
| }); |
| }, "reject/finally-return-rejected-promise/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.resolve(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.resolve(4); |
| }) |
| .then(x => { |
| assert.equals(3, x); |
| }, assert.unreachable); |
| }, "resolve/finally-return-resolved-promise/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.resolve(4); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(3, e); |
| }); |
| }, "reject/finally-return-resolved-promise/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| Promise.reject(3) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.resolve(4); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(3, e); |
| }); |
| }, "reject/finally-return-resolved-promise/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var thenable = { |
| then: function(onResolve, onReject) { |
| onResolve(5); |
| } |
| }; |
| |
| Promise.resolve(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return thenable; |
| }) |
| .then(x => { |
| assert.equals(5, x); |
| }, assert.unreachable); |
| }, "resolve/finally-thenable-resolve/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var thenable = { |
| then: function(onResolve, onReject) { |
| onResolve(1); |
| } |
| }; |
| |
| Promise.reject(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return thenable; |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(5, e); |
| }); |
| }, "reject/finally-thenable-resolve/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var thenable = { |
| then: function(onResolve, onReject) { |
| onReject(1); |
| } |
| }; |
| |
| Promise.reject(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return thenable; |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "reject/finally-thenable-reject/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var thenable = { |
| then: function(onResolve, onReject) { |
| onReject(1); |
| } |
| }; |
| |
| Promise.resolve(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return thenable; |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "resolve/finally-thenable-reject/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.resolve(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(x => { |
| assert.equals(5, x); |
| }, assert.unreachable); |
| }, "resolve/finally/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.resolve(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| throw 1; |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "resolve/finally-throw/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.resolve(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.reject(1); |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "resolve/finally-return-rejected-promise/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.reject(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(5, e); |
| }); |
| }, "reject/finally/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.reject(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| throw 1; |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "reject/finally-throw/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| |
| Promise.reject(5) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return Promise.reject(1); |
| }) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(1, e); |
| }); |
| }, "reject/finally-return-rejected-promise/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var resolve, reject; |
| var deferred = new Promise((x, y) => { |
| resolve = x; |
| reject = y; |
| }); |
| |
| Promise.resolve(1) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return deferred; |
| }) |
| .then(x => { |
| assert.equals(1, x); |
| }, assert.unreachable); |
| |
| resolve(5); |
| }, "resolve/finally-deferred-resolve/then"); |
| |
| // |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var resolve, reject; |
| var deferred = new Promise((x, y) => { |
| resolve = x; |
| reject = y; |
| }); |
| Promise.resolve(1) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| return deferred; |
| }) |
| .then(assert.unreachable, e => { |
| assert.equals(5, e); |
| }); |
| |
| reject(5); |
| }, "resolve/finally-deferred-reject/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var resolve, reject; |
| var deferred = new Promise((x, y) => { |
| resolve = x; |
| reject = y; |
| }); |
| Promise.all([deferred]) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(([x]) => { |
| assert.equals(1, x); |
| }, assert.unreachable); |
| |
| resolve(1); |
| }, "all/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| var resolve, reject; |
| var d1 = new Promise((x, y) => { |
| resolve = x; |
| reject = y; |
| }); |
| var d2 = new Promise((x, y) => { |
| resolve = x; |
| reject = y; |
| }); |
| Promise.race([d1, d2]) |
| .finally(function onFinally() { |
| assert.equals(0, arguments.length); |
| }) |
| .then(x => { |
| assert.equals(1, x); |
| }, assert.unreachable); |
| |
| resolve(1); |
| }, "race/finally/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| class MyPromise extends Promise { |
| then(onFulfilled, onRejected) { |
| assert.equals(5, onFulfilled); |
| assert.equals(5, onRejected); |
| return super.then(onFulfilled, onRejected); |
| } |
| } |
| |
| MyPromise.resolve(3).finally(5); |
| }, "resolve/finally-customthen/then"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| class MyPromise extends Promise { |
| then(onFulfilled, onRejected) { |
| assert.equals(5, onFulfilled); |
| assert.equals(5, onRejected); |
| return super.then(onFulfilled, onRejected); |
| } |
| } |
| |
| MyPromise.reject(3).finally(5); |
| }, "reject/finally-customthen/then"); |
| |
| var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, "finally"); |
| assertTrue(descriptor.writable); |
| assertTrue(descriptor.configurable); |
| assertFalse(descriptor.enumerable); |
| assertEquals("finally", Promise.prototype.finally.name); |
| assertEquals(1, Promise.prototype.finally.length); |
| |
| var count = 0; |
| class FooPromise extends Promise { |
| constructor(resolve, reject) { |
| count++; |
| return super(resolve, reject); |
| } |
| } |
| |
| testAsync(assert => { |
| assert.plan(1); |
| count = 0; |
| |
| new FooPromise(r => r()).finally(() => {}).then(() => { |
| assert.equals(6, count); |
| }); |
| }, "finally/speciesconstructor"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| count = 0; |
| |
| FooPromise.resolve().finally(() => {}).then(() => { |
| assert.equals(6, count); |
| }) |
| }, "resolve/finally/speciesconstructor"); |
| |
| testAsync(assert => { |
| assert.plan(1); |
| count = 0; |
| |
| FooPromise.reject().finally(() => {}).catch(() => { |
| assert.equals(6, count); |
| }) |
| }, "reject/finally/speciesconstructor"); |
| |
| testAsync(assert => { |
| assert.plan(2); |
| |
| class MyPromise extends Promise { |
| static get [Symbol.species]() { return Promise; } |
| } |
| |
| var p = Promise |
| .resolve() |
| .finally(() => MyPromise.resolve()); |
| |
| assert.equals(true, p instanceof Promise); |
| assert.equals(false, p instanceof MyPromise); |
| }, "finally/Symbol.Species"); |
| |
| testAsync(assert => { |
| assert.plan(3); |
| let resolve; |
| let value = 0; |
| |
| let p = new Promise(r => { resolve = r }); |
| |
| Promise.resolve() |
| .finally(() => { |
| return p; |
| }) |
| .then(() => { |
| value = 1; |
| }); |
| |
| // This makes sure we take the fast path in PromiseResolve that just |
| // returns the promise it receives as value. If we had to create |
| // another wrapper promise, that would cause an additional tick in |
| // the microtask queue. |
| Promise.resolve() |
| // onFinally has run. |
| .then(() => { resolve(); }) |
| // thenFinally has run. |
| .then(() => assert.equals(0, value)) |
| // promise returned by .finally has been resolved. |
| .then(() => assert.equals(0, value)) |
| // onFulfilled callback of .then() has run. |
| .then(() => assert.equals(1, value)); |
| |
| }, "PromiseResolve-ordering"); |
| |
| (function testIsObject() { |
| var called = false; |
| var p = new Proxy(Promise.resolve(), {}); |
| var oldThen = Promise.prototype.then; |
| Promise.prototype.then = () => called = true; |
| Promise.prototype.finally.call(p); |
| assertTrue(called); |
| Promise.prototype.then = oldThen; |
| })(); |