1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 // Flags: --allow-natives-syntax --harmony-tostring
30 // Make sure we don't rely on functions patchable by monkeys.
31 var call = Function.prototype.call.call.bind(Function.prototype.call)
32 var observe = Object.observe;
33 var getOwnPropertyNames = Object.getOwnPropertyNames;
34 var defineProperty = Object.defineProperty;
38 // Test before clearing global (fails otherwise)
39 assertEquals("[object Promise]",
40 Object.prototype.toString.call(new Promise(function() {})));
45 if (o === null || (typeof o !== 'object' && typeof o !== 'function')) return
47 var properties = getOwnPropertyNames(o)
48 for (var i in properties) {
49 clearProp(o, properties[i])
53 function clearProp(o, name) {
54 var poisoned = {caller: 0, callee: 0, arguments: 0}
59 } catch(e) {} // assertTrue(name in poisoned) }
62 // Find intrinsics and null them out.
63 var globals = Object.getOwnPropertyNames(this)
64 var whitelist = {Promise: true, TypeError: true}
65 for (var i in globals) {
67 if (name in whitelist || name[0] === name[0].toLowerCase()) delete globals[i]
69 for (var i in globals) {
70 if (globals[i]) clearProp(this, globals[i])
74 var asyncAssertsExpected = 0;
76 function assertAsyncRan() { ++asyncAssertsExpected }
78 function assertAsync(b, s) {
82 %AbortJS(s + " FAILED!") // Simply throwing here will have no effect.
84 --asyncAssertsExpected
87 function assertAsyncDone(iteration) {
88 var iteration = iteration || 0
92 if (asyncAssertsExpected === 0)
93 assertAsync(true, "all")
94 else if (iteration > 10) // Shouldn't take more.
95 assertAsync(false, "all")
97 assertAsyncDone(iteration + 1)
105 assertThrows(function() { Promise(function() {}) }, TypeError)
109 assertTrue(new Promise(function() {}) instanceof Promise)
113 assertThrows(function() { new Promise(5) }, TypeError)
117 assertDoesNotThrow(function() { new Promise(function() { throw 5 }) })
121 (new Promise(function() { throw 5 })).chain(
123 function(r) { assertAsync(r === 5, "new-throw") }
130 Promise.accept(5).chain(undefined, assertUnreachable).chain(
131 function(x) { assertAsync(x === 5, "resolved/chain-nohandler") },
138 Promise.reject(5).chain(assertUnreachable, undefined).chain(
140 function(r) { assertAsync(r === 5, "rejected/chain-nohandler") }
146 Promise.accept(5).then(undefined, assertUnreachable).chain(
147 function(x) { assertAsync(x === 5, "resolved/then-nohandler-undefined") },
151 Promise.accept(6).then(null, assertUnreachable).chain(
152 function(x) { assertAsync(x === 6, "resolved/then-nohandler-null") },
159 Promise.reject(5).then(assertUnreachable, undefined).chain(
161 function(r) { assertAsync(r === 5, "rejected/then-nohandler-undefined") }
164 Promise.reject(6).then(assertUnreachable, null).chain(
166 function(r) { assertAsync(r === 6, "rejected/then-nohandler-null") }
172 var p1 = Promise.accept(5)
173 var p2 = Promise.accept(p1)
174 var p3 = Promise.accept(p2)
176 function(x) { assertAsync(x === p2, "resolved/chain") },
183 var p1 = Promise.accept(5)
184 var p2 = Promise.accept(p1)
185 var p3 = Promise.accept(p2)
187 function(x) { assertAsync(x === 5, "resolved/then") },
194 var p1 = Promise.reject(5)
195 var p2 = Promise.accept(p1)
196 var p3 = Promise.accept(p2)
198 function(x) { assertAsync(x === p2, "rejected/chain") },
205 var p1 = Promise.reject(5)
206 var p2 = Promise.accept(p1)
207 var p3 = Promise.accept(p2)
210 function(x) { assertAsync(x === 5, "rejected/then") }
216 var p1 = Promise.accept(5)
217 var p2 = Promise.accept(p1)
218 var p3 = Promise.accept(p2)
219 p3.chain(function(x) { return x }, assertUnreachable).chain(
220 function(x) { assertAsync(x === p1, "resolved/chain/chain") },
227 var p1 = Promise.accept(5)
228 var p2 = Promise.accept(p1)
229 var p3 = Promise.accept(p2)
230 p3.chain(function(x) { return x }, assertUnreachable).then(
231 function(x) { assertAsync(x === 5, "resolved/chain/then") },
238 var p1 = Promise.accept(5)
239 var p2 = Promise.accept(p1)
240 var p3 = Promise.accept(p2)
241 p3.chain(function(x) { return 6 }, assertUnreachable).chain(
242 function(x) { assertAsync(x === 6, "resolved/chain/chain2") },
249 var p1 = Promise.accept(5)
250 var p2 = Promise.accept(p1)
251 var p3 = Promise.accept(p2)
252 p3.chain(function(x) { return 6 }, assertUnreachable).then(
253 function(x) { assertAsync(x === 6, "resolved/chain/then2") },
260 var p1 = Promise.accept(5)
261 var p2 = Promise.accept(p1)
262 var p3 = Promise.accept(p2)
263 p3.then(function(x) { return x + 1 }, assertUnreachable).chain(
264 function(x) { assertAsync(x === 6, "resolved/then/chain") },
271 var p1 = Promise.accept(5)
272 var p2 = Promise.accept(p1)
273 var p3 = Promise.accept(p2)
274 p3.then(function(x) { return x + 1 }, assertUnreachable).then(
275 function(x) { assertAsync(x === 6, "resolved/then/then") },
282 var p1 = Promise.accept(5)
283 var p2 = Promise.accept(p1)
284 var p3 = Promise.accept(p2)
285 p3.then(function(x){ return Promise.accept(x+1) }, assertUnreachable).chain(
286 function(x) { assertAsync(x === 6, "resolved/then/chain2") },
293 var p1 = Promise.accept(5)
294 var p2 = Promise.accept(p1)
295 var p3 = Promise.accept(p2)
296 p3.then(function(x) { return Promise.accept(x+1) }, assertUnreachable).then(
297 function(x) { assertAsync(x === 6, "resolved/then/then2") },
304 var p1 = Promise.accept(5)
305 var p2 = Promise.accept(p1)
306 var p3 = Promise.accept(p2)
307 p3.chain(function(x) { throw 6 }, assertUnreachable).chain(
309 function(x) { assertAsync(x === 6, "resolved/chain-throw/chain") }
315 var p1 = Promise.accept(5)
316 var p2 = Promise.accept(p1)
317 var p3 = Promise.accept(p2)
318 p3.chain(function(x) { throw 6 }, assertUnreachable).then(
320 function(x) { assertAsync(x === 6, "resolved/chain-throw/then") }
326 var p1 = Promise.accept(5)
327 var p2 = Promise.accept(p1)
328 var p3 = Promise.accept(p2)
329 p3.then(function(x) { throw 6 }, assertUnreachable).chain(
331 function(x) { assertAsync(x === 6, "resolved/then-throw/chain") }
337 var p1 = Promise.accept(5)
338 var p2 = Promise.accept(p1)
339 var p3 = Promise.accept(p2)
340 p3.then(function(x) { throw 6 }, assertUnreachable).then(
342 function(x) { assertAsync(x === 6, "resolved/then-throw/then") }
348 var p1 = Promise.accept(5)
349 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
350 var p3 = Promise.accept(p2)
352 function(x) { assertAsync(x === p2, "resolved/thenable/chain") },
359 var p1 = Promise.accept(5)
360 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
361 var p3 = Promise.accept(p2)
363 function(x) { assertAsync(x === 5, "resolved/thenable/then") },
370 var p1 = Promise.reject(5)
371 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
372 var p3 = Promise.accept(p2)
374 function(x) { assertAsync(x === p2, "rejected/thenable/chain") },
381 var p1 = Promise.reject(5)
382 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
383 var p3 = Promise.accept(p2)
386 function(x) { assertAsync(x === 5, "rejected/thenable/then") }
392 var deferred = Promise.defer()
393 var p1 = deferred.promise
394 var p2 = Promise.accept(p1)
395 var p3 = Promise.accept(p2)
397 function(x) { assertAsync(x === p2, "chain/resolve") },
405 var deferred = Promise.defer()
406 var p1 = deferred.promise
407 var p2 = Promise.accept(p1)
408 var p3 = Promise.accept(p2)
410 function(x) { assertAsync(x === 5, "then/resolve") },
418 var deferred = Promise.defer()
419 var p1 = deferred.promise
420 var p2 = Promise.accept(p1)
421 var p3 = Promise.accept(p2)
423 function(x) { assertAsync(x === p2, "chain/reject") },
431 var deferred = Promise.defer()
432 var p1 = deferred.promise
433 var p2 = Promise.accept(p1)
434 var p3 = Promise.accept(p2)
437 function(x) { assertAsync(x === 5, "then/reject") }
444 var deferred = Promise.defer()
445 var p1 = deferred.promise
446 var p2 = p1.then(1, 2)
448 function(x) { assertAsync(x === 5, "then/resolve-non-function") },
456 var deferred = Promise.defer()
457 var p1 = deferred.promise
458 var p2 = p1.then(1, 2)
461 function(x) { assertAsync(x === 5, "then/reject-non-function") }
468 var deferred = Promise.defer()
469 var p1 = deferred.promise
470 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
471 var p3 = Promise.accept(p2)
473 function(x) { assertAsync(x === p2, "chain/resolve/thenable") },
481 var deferred = Promise.defer()
482 var p1 = deferred.promise
483 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
484 var p3 = Promise.accept(p2)
486 function(x) { assertAsync(x === 5, "then/resolve/thenable") },
494 var deferred = Promise.defer()
495 var p1 = deferred.promise
496 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
497 var p3 = Promise.accept(p2)
499 function(x) { assertAsync(x === p2, "chain/reject/thenable") },
507 var deferred = Promise.defer()
508 var p1 = deferred.promise
509 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
510 var p3 = Promise.accept(p2)
513 function(x) { assertAsync(x === 5, "then/reject/thenable") }
520 var p1 = Promise.accept(5)
521 var p2 = Promise.accept(p1)
522 var deferred = Promise.defer()
523 var p3 = deferred.promise
525 function(x) { assertAsync(x === p2, "chain/resolve2") },
533 var p1 = Promise.accept(5)
534 var p2 = Promise.accept(p1)
535 var deferred = Promise.defer()
536 var p3 = deferred.promise
538 function(x) { assertAsync(x === 5, "then/resolve2") },
546 var p1 = Promise.accept(5)
547 var p2 = Promise.accept(p1)
548 var deferred = Promise.defer()
549 var p3 = deferred.promise
552 function(x) { assertAsync(x === 5, "chain/reject2") }
559 var p1 = Promise.accept(5)
560 var p2 = Promise.accept(p1)
561 var deferred = Promise.defer()
562 var p3 = deferred.promise
565 function(x) { assertAsync(x === 5, "then/reject2") }
572 var p1 = Promise.accept(5)
573 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
574 var deferred = Promise.defer()
575 var p3 = deferred.promise
577 function(x) { assertAsync(x === p2, "chain/resolve/thenable2") },
585 var p1 = Promise.accept(5)
586 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
587 var deferred = Promise.defer()
588 var p3 = deferred.promise
590 function(x) { assertAsync(x === 5, "then/resolve/thenable2") },
598 var p1 = Promise.accept(0)
599 var p2 = p1.chain(function(x) { return p2 }, assertUnreachable)
602 function(r) { assertAsync(r instanceof TypeError, "cyclic/chain") }
608 var p1 = Promise.accept(0)
609 var p2 = p1.then(function(x) { return p2 }, assertUnreachable)
612 function(r) { assertAsync(r instanceof TypeError, "cyclic/then") }
618 var deferred = Promise.defer()
619 var p = deferred.promise
622 function(x) { assertAsync(x === p, "cyclic/deferred/chain") },
629 var deferred = Promise.defer()
630 var p = deferred.promise
634 function(r) { assertAsync(r instanceof TypeError, "cyclic/deferred/then") }
640 Promise.all({}).chain(
642 function(r) { assertAsync(r instanceof TypeError, "all/no-array") }
648 Promise.all([]).chain(
649 function(x) { assertAsync(x.length === 0, "all/resolve/empty") },
656 var deferred1 = Promise.defer()
657 var p1 = deferred1.promise
658 var deferred2 = Promise.defer()
659 var p2 = deferred2.promise
660 var deferred3 = Promise.defer()
661 var p3 = deferred3.promise
662 Promise.all([p1, p2, p3]).chain(
664 assertAsync(x.length === 3, "all/resolve")
665 assertAsync(x[0] === 1, "all/resolve/0")
666 assertAsync(x[1] === 2, "all/resolve/1")
667 assertAsync(x[2] === 3, "all/resolve/2")
681 var deferred = Promise.defer()
682 var p1 = deferred.promise
683 var p2 = Promise.accept(2)
684 var p3 = Promise.defer().promise
685 Promise.all([p1, p2, p3]).chain(
693 var deferred1 = Promise.defer()
694 var p1 = deferred1.promise
695 var deferred2 = Promise.defer()
696 var p2 = deferred2.promise
697 var deferred3 = Promise.defer()
698 var p3 = deferred3.promise
699 Promise.all([p1, p2, p3]).chain(
701 function(x) { assertAsync(x === 2, "all/reject") }
710 Promise.race([]).chain(
717 var p1 = Promise.accept(1)
718 var p2 = Promise.accept(2)
719 var p3 = Promise.accept(3)
720 Promise.race([p1, p2, p3]).chain(
721 function(x) { assertAsync(x === 1, "resolved/one") },
728 var p1 = Promise.accept(1)
729 var p2 = Promise.accept(2)
730 var p3 = Promise.accept(3)
731 Promise.race([0, p1, p2, p3]).chain(
732 function(x) { assertAsync(x === 0, "resolved-const/one") },
739 Promise.race({}).chain(
741 function(r) { assertAsync(r instanceof TypeError, "one/no-array") }
747 var deferred1 = Promise.defer()
748 var p1 = deferred1.promise
749 var deferred2 = Promise.defer()
750 var p2 = deferred2.promise
751 var deferred3 = Promise.defer()
752 var p3 = deferred3.promise
753 Promise.race([p1, p2, p3]).chain(
754 function(x) { assertAsync(x === 3, "one/resolve") },
763 var deferred = Promise.defer()
764 var p1 = deferred.promise
765 var p2 = Promise.accept(2)
766 var p3 = Promise.defer().promise
767 Promise.race([p1, p2, p3]).chain(
768 function(x) { assertAsync(x === 2, "resolved/one") },
776 var deferred1 = Promise.defer()
777 var p1 = deferred1.promise
778 var deferred2 = Promise.defer()
779 var p2 = deferred2.promise
780 var deferred3 = Promise.defer()
781 var p3 = deferred3.promise
782 Promise.race([p1, p2, p3]).chain(
783 function(x) { assertAsync(x === 3, "one/resolve/reject") },
792 var deferred1 = Promise.defer()
793 var p1 = deferred1.promise
794 var deferred2 = Promise.defer()
795 var p2 = deferred2.promise
796 var deferred3 = Promise.defer()
797 var p3 = deferred3.promise
798 Promise.race([p1, p2, p3]).chain(
800 function(x) { assertAsync(x === 3, "one/reject/resolve") }
809 function MyPromise(resolver) {
811 var promise = new Promise(function(resolve, reject) {
813 function(x) { log += "x" + x; resolve(x) },
814 function(r) { log += "r" + r; reject(r) }
817 promise.__proto__ = MyPromise.prototype
821 MyPromise.__proto__ = Promise
822 MyPromise.defer = function() {
824 return call(this.__proto__.defer, this)
827 MyPromise.prototype.__proto__ = Promise.prototype
828 MyPromise.prototype.chain = function(resolve, reject) {
830 return call(this.__proto__.__proto__.chain, this, resolve, reject)
834 var p1 = new MyPromise(function(resolve, reject) { resolve(1) })
835 var p2 = new MyPromise(function(resolve, reject) { reject(2) })
836 var d3 = MyPromise.defer()
837 assertTrue(d3.promise instanceof Promise, "subclass/instance")
838 assertTrue(d3.promise instanceof MyPromise, "subclass/instance-my3")
839 assertTrue(log === "nx1nr2dn", "subclass/create")
842 var p4 = MyPromise.resolve(4)
843 var p5 = MyPromise.reject(5)
844 assertTrue(p4 instanceof Promise, "subclass/instance4")
845 assertTrue(p4 instanceof MyPromise, "subclass/instance-my4")
846 assertTrue(p5 instanceof Promise, "subclass/instance5")
847 assertTrue(p5 instanceof MyPromise, "subclass/instance-my5")
849 assertTrue(log === "nx4nr5x3", "subclass/resolve")
852 var d6 = MyPromise.defer()
853 d6.promise.chain(function(x) {
854 return new Promise(function(resolve) { resolve(x) })
855 }).chain(function() {})
857 assertTrue(log === "dncncnx6", "subclass/chain")
860 Promise.all([11, Promise.accept(12), 13, MyPromise.accept(14), 15, 16])
861 assertTrue(log === "nx14n", "subclass/all/arg")
864 MyPromise.all([21, Promise.accept(22), 23, MyPromise.accept(24), 25, 26])
865 assertTrue(log === "nx24nnx21nnx23nnnx25nnx26n", "subclass/all/self")