promise-prototype-finally.js 13.3 KB
Newer Older
1 2 3 4
// 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.

5
// Flags: --allow-natives-syntax
6

7
assertThrows(() => Promise.prototype.finally.call(5), TypeError);
8

9 10
testAsync(assert => {
  assert.plan(1);
11

12 13 14 15
  Promise.resolve(3).finally().then(x => {
    assert.equals(3, x);
  }, assert.unreachable);
}, "resolve/finally/then");
16

17 18 19 20 21
testAsync(assert => {
  assert.plan(1);

  Promise.reject(3).finally().then(assert.unreachable, x => {
    assert.equals(3, x);
22
  });
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
}, "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);
38
  });
39 40 41 42
}, "reject/finally-return-notcallable/then");

testAsync(assert => {
  assert.plan(1);
43 44

  Promise.reject(3).finally().catch(reason => {
45
    assert.equals(3, reason);
46
  });
47
}, "reject/finally/catch");
48

49 50 51 52 53
testAsync(assert => {
  assert.plan(1);

  Promise.reject(3).finally().then(assert.unreachable).catch(reason => {
    assert.equals(3, reason);
54
  });
55 56 57 58
}, "reject/finally/then/catch");

testAsync(assert => {
  assert.plan(2);
59 60 61

  Promise.resolve(3)
    .then(x => {
62
      assert.equals(3, x);
63 64 65
      return x;
    })
    .finally()
66 67 68 69 70 71 72 73
    .then(x => {
      assert.equals(3, x);
    }, assert.unreachable);
}, "resolve/then/finally/then");

testAsync(assert => {
  assert.plan(2);

74 75
  Promise.reject(3)
    .catch(x => {
76
      assert.equals(3, x);
77 78 79
      return x;
    })
    .finally()
80 81 82 83 84 85 86 87
    .then(x => {
      assert.equals(3, x);
    }, assert.unreachable);
}, "reject/catch/finally/then");

testAsync(assert => {
  assert.plan(2);

88 89
  Promise.resolve(3)
    .finally(function onFinally() {
90 91
      print("in finally");
      assert.equals(0, arguments.length);
92 93
      throw 1;
    })
94 95
    .then(assert.unreachable, function onRejected(reason) {
      assert.equals(1, reason);
96
    });
97 98 99 100
}, "resolve/finally-throw/then");

testAsync(assert => {
  assert.plan(2);
101 102 103

  Promise.reject(3)
    .finally(function onFinally() {
104
      assert.equals(0, arguments.length);
105 106
      throw 1;
    })
107 108
    .then(assert.unreachable, function onRejected(reason) {
      assert.equals(1, reason);
109
    });
110 111 112 113
}, "reject/finally-throw/then");

testAsync(assert => {
  assert.plan(2);
114 115 116

  Promise.resolve(3)
    .finally(function onFinally() {
117
      assert.equals(0, arguments.length);
118 119
      return 4;
    })
120 121 122 123
    .then(x => {
      assert.equals(x, 3);
    }, assert.unreachable);
}, "resolve/finally-return/then");
124 125

// reject/finally-return/then
126 127 128
testAsync(assert => {
  assert.plan(2);

129 130
  Promise.reject(3)
    .finally(function onFinally() {
131
      assert.equals(0, arguments.length);
132 133
      return 4;
    })
134 135
    .then(assert.unreachable, x => {
      assert.equals(x, 3);
136
    });
137
});
138 139

// reject/catch-throw/finally-throw/then
140 141 142
testAsync(assert => {
  assert.plan(3);

143 144
  Promise.reject(3)
    .catch(e => {
145
      assert.equals(3, e);
146 147 148
      throw e;
    })
    .finally(function onFinally() {
149
      assert.equals(0, arguments.length);
150 151
      throw 4;
    })
152 153
    .then(assert.unreachable, function onRejected(e) {
      assert.equals(4, e);
154
    });
155 156 157 158
});

testAsync(assert => {
  assert.plan(3);
159 160 161

  Promise.resolve(3)
    .then(e => {
162
      assert.equals(3, e);
163 164 165
      throw e;
    })
    .finally(function onFinally() {
166
      assert.equals(0, arguments.length);
167 168
      throw 4;
    })
169 170
    .then(assert.unreachable, function onRejected(e) {
      assert.equals(4, e);
171
    });
172 173 174 175
}, "resolve/then-throw/finally-throw/then");

testAsync(assert => {
  assert.plan(2);
176 177 178

  Promise.resolve(3)
    .finally(function onFinally() {
179
      assert.equals(0, arguments.length);
180 181
      return Promise.reject(4);
    })
182 183
    .then(assert.unreachable, e => {
      assert.equals(4, e);
184
    });
185 186 187 188
}, "resolve/finally-return-rejected-promise/then");

testAsync(assert => {
  assert.plan(2);
189 190 191

  Promise.reject(3)
    .finally(function onFinally() {
192
      assert.equals(0, arguments.length);
193 194
      return Promise.reject(4);
    })
195 196
    .then(assert.unreachable, e => {
      assert.equals(4, e);
197
    });
198 199 200 201
}, "reject/finally-return-rejected-promise/then");

testAsync(assert => {
  assert.plan(2);
202 203 204

  Promise.resolve(3)
    .finally(function onFinally() {
205
      assert.equals(0, arguments.length);
206 207
      return Promise.resolve(4);
    })
208 209 210 211 212 213 214 215
    .then(x => {
      assert.equals(3, x);
    }, assert.unreachable);
}, "resolve/finally-return-resolved-promise/then");

testAsync(assert => {
  assert.plan(2);

216 217
  Promise.reject(3)
    .finally(function onFinally() {
218
      assert.equals(0, arguments.length);
219 220
      return Promise.resolve(4);
    })
221 222
    .then(assert.unreachable, e => {
      assert.equals(3, e);
223
    });
224 225 226 227
}, "reject/finally-return-resolved-promise/then");

testAsync(assert => {
  assert.plan(2);
228 229 230

  Promise.reject(3)
    .finally(function onFinally() {
231
      assert.equals(0, arguments.length);
232 233
      return Promise.resolve(4);
    })
234 235
    .then(assert.unreachable, e => {
      assert.equals(3, e);
236
    });
237 238 239 240
}, "reject/finally-return-resolved-promise/then");

testAsync(assert => {
  assert.plan(2);
241 242 243 244 245 246 247 248 249

  var thenable = {
    then: function(onResolve, onReject) {
      onResolve(5);
    }
  };

  Promise.resolve(5)
    .finally(function onFinally() {
250
      assert.equals(0, arguments.length);
251 252
      return thenable;
    })
253 254 255 256
    .then(x => {
      assert.equals(5, x);
    }, assert.unreachable);
}, "resolve/finally-thenable-resolve/then");
257

258 259
testAsync(assert => {
  assert.plan(2);
260 261 262 263 264 265 266 267 268

  var thenable = {
    then: function(onResolve, onReject) {
      onResolve(1);
    }
  };

  Promise.reject(5)
    .finally(function onFinally() {
269
      assert.equals(0, arguments.length);
270 271
      return thenable;
    })
272 273
    .then(assert.unreachable, e => {
      assert.equals(5, e);
274
    });
275
}, "reject/finally-thenable-resolve/then");
276

277 278
testAsync(assert => {
  assert.plan(2);
279 280 281 282 283 284 285 286 287

  var thenable = {
    then: function(onResolve, onReject) {
      onReject(1);
    }
  };

  Promise.reject(5)
    .finally(function onFinally() {
288
      assert.equals(0, arguments.length);
289 290
      return thenable;
    })
291 292
    .then(assert.unreachable, e => {
      assert.equals(1, e);
293
    });
294
}, "reject/finally-thenable-reject/then");
295

296 297
testAsync(assert => {
  assert.plan(2);
298 299 300 301 302 303 304 305 306

  var thenable = {
    then: function(onResolve, onReject) {
      onReject(1);
    }
  };

  Promise.resolve(5)
    .finally(function onFinally() {
307
      assert.equals(0, arguments.length);
308 309
      return thenable;
    })
310 311
    .then(assert.unreachable, e => {
      assert.equals(1, e);
312
    });
313
}, "resolve/finally-thenable-reject/then");
314

315 316
testAsync(assert => {
  assert.plan(3);
317 318 319

  Promise.resolve(5)
    .finally(function onFinally() {
320
      assert.equals(0, arguments.length);
321 322
    })
    .finally(function onFinally() {
323 324 325 326 327 328 329 330 331 332
      assert.equals(0, arguments.length);
    })
    .then(x => {
      assert.equals(5, x);
    }, assert.unreachable);
}, "resolve/finally/finally/then");

testAsync(assert => {
  assert.plan(3);

333 334
  Promise.resolve(5)
    .finally(function onFinally() {
335
      assert.equals(0, arguments.length);
336 337 338
      throw 1;
    })
    .finally(function onFinally() {
339
      assert.equals(0, arguments.length);
340
    })
341 342
    .then(assert.unreachable, e => {
      assert.equals(1, e);
343
    });
344
}, "resolve/finally-throw/finally/then");
345

346 347
testAsync(assert => {
  assert.plan(3);
348 349 350

  Promise.resolve(5)
    .finally(function onFinally() {
351
      assert.equals(0, arguments.length);
352 353 354
      return Promise.reject(1);
    })
    .finally(function onFinally() {
355
      assert.equals(0, arguments.length);
356
    })
357 358
    .then(assert.unreachable, e => {
      assert.equals(1, e);
359
    });
360
}, "resolve/finally-return-rejected-promise/finally/then");
361

362 363
testAsync(assert => {
  assert.plan(3);
364 365 366

  Promise.reject(5)
    .finally(function onFinally() {
367
      assert.equals(0, arguments.length);
368 369
    })
    .finally(function onFinally() {
370
      assert.equals(0, arguments.length);
371
    })
372 373
    .then(assert.unreachable, e => {
      assert.equals(5, e);
374
    });
375
}, "reject/finally/finally/then");
376

377 378
testAsync(assert => {
  assert.plan(3);
379 380 381

  Promise.reject(5)
    .finally(function onFinally() {
382
      assert.equals(0, arguments.length);
383 384 385
      throw 1;
    })
    .finally(function onFinally() {
386
      assert.equals(0, arguments.length);
387
    })
388 389
    .then(assert.unreachable, e => {
      assert.equals(1, e);
390
    });
391
}, "reject/finally-throw/finally/then");
392

393 394
testAsync(assert => {
  assert.plan(3);
395 396 397

  Promise.reject(5)
    .finally(function onFinally() {
398
      assert.equals(0, arguments.length);
399 400 401
      return Promise.reject(1);
    })
    .finally(function onFinally() {
402
      assert.equals(0, arguments.length);
403
    })
404 405
    .then(assert.unreachable, e => {
      assert.equals(1, e);
406
    });
407
}, "reject/finally-return-rejected-promise/finally/then");
408

409 410
testAsync(assert => {
  assert.plan(2);
411 412 413 414 415 416

  var resolve, reject;
  var deferred = new Promise((x, y) => {
    resolve = x;
    reject = y;
  });
417

418 419
  Promise.resolve(1)
    .finally(function onFinally() {
420
      assert.equals(0, arguments.length);
421 422
      return deferred;
    })
423 424 425
    .then(x => {
      assert.equals(1, x);
    }, assert.unreachable);
426 427

  resolve(5);
428 429 430 431 432
}, "resolve/finally-deferred-resolve/then");

//
testAsync(assert => {
  assert.plan(2);
433 434 435 436 437 438 439 440

  var resolve, reject;
  var deferred = new Promise((x, y) => {
    resolve = x;
    reject = y;
  });
  Promise.resolve(1)
    .finally(function onFinally() {
441
      assert.equals(0, arguments.length);
442 443
      return deferred;
    })
444 445
    .then(assert.unreachable, e => {
      assert.equals(5, e);
446 447 448
    });

  reject(5);
449 450 451 452
}, "resolve/finally-deferred-reject/then");

testAsync(assert => {
  assert.plan(2);
453 454 455 456 457 458 459 460

  var resolve, reject;
  var deferred = new Promise((x, y) => {
    resolve = x;
    reject = y;
  });
  Promise.all([deferred])
    .finally(function onFinally() {
461
      assert.equals(0, arguments.length);
462
    })
463 464 465
    .then(([x]) => {
      assert.equals(1, x);
    }, assert.unreachable);
466 467

  resolve(1);
468 469 470 471
}, "all/finally/then");

testAsync(assert => {
  assert.plan(2);
472 473 474 475 476 477 478 479 480 481 482 483

  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() {
484
      assert.equals(0, arguments.length);
485
    })
486 487 488
    .then(x => {
      assert.equals(1, x);
    }, assert.unreachable);
489 490

  resolve(1);
491 492 493 494
}, "race/finally/then");

testAsync(assert => {
  assert.plan(2);
495 496

  class MyPromise extends Promise {
497 498 499 500 501
    then(onFulfilled, onRejected) {
      assert.equals(5, onFulfilled);
      assert.equals(5, onRejected);
      return super.then(onFulfilled, onRejected);
    }
502 503 504
  }

  MyPromise.resolve(3).finally(5);
505
}, "resolve/finally-customthen/then");
506

507 508
testAsync(assert => {
  assert.plan(2);
509 510

  class MyPromise extends Promise {
511 512 513 514 515
    then(onFulfilled, onRejected) {
      assert.equals(5, onFulfilled);
      assert.equals(5, onRejected);
      return super.then(onFulfilled, onRejected);
    }
516 517 518
  }

  MyPromise.reject(3).finally(5);
519
}, "reject/finally-customthen/then");
520

521
var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, "finally");
522 523 524 525 526
assertTrue(descriptor.writable);
assertTrue(descriptor.configurable);
assertFalse(descriptor.enumerable);
assertEquals("finally", Promise.prototype.finally.name);
assertEquals(1, Promise.prototype.finally.length);
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607

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");
608 609 610 611 612 613 614 615 616 617

(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;
})();