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;
35 var numberPrototype = Number.prototype;
36 var symbolIterator = Symbol.iterator;
40 // Test before clearing global (fails otherwise)
41 assertEquals("[object Promise]",
42 Object.prototype.toString.call(new Promise(function() {})));
47 if (o === null || (typeof o !== 'object' && typeof o !== 'function')) return
49 var properties = getOwnPropertyNames(o)
50 for (var i in properties) {
51 clearProp(o, properties[i])
55 function clearProp(o, name) {
56 var poisoned = {caller: 0, callee: 0, arguments: 0}
61 } catch(e) {} // assertTrue(name in poisoned) }
64 // Find intrinsics and null them out.
65 var globals = Object.getOwnPropertyNames(this)
66 var whitelist = {Promise: true, TypeError: true}
67 for (var i in globals) {
69 if (name in whitelist || name[0] === name[0].toLowerCase()) delete globals[i]
71 for (var i in globals) {
72 if (globals[i]) clearProp(this, globals[i])
76 var asyncAssertsExpected = 0;
78 function assertAsyncRan() { ++asyncAssertsExpected }
80 function assertAsync(b, s) {
84 %AbortJS(s + " FAILED!") // Simply throwing here will have no effect.
86 --asyncAssertsExpected
89 function assertAsyncDone(iteration) {
90 var iteration = iteration || 0
94 if (asyncAssertsExpected === 0)
95 assertAsync(true, "all")
96 else if (iteration > 10) // Shouldn't take more.
97 assertAsync(false, "all")
99 assertAsyncDone(iteration + 1)
107 assertThrows(function() { Promise(function() {}) }, TypeError)
111 assertTrue(new Promise(function() {}) instanceof Promise)
115 assertThrows(function() { new Promise(5) }, TypeError)
119 assertDoesNotThrow(function() { new Promise(function() { throw 5 }) })
123 (new Promise(function() { throw 5 })).chain(
125 function(r) { assertAsync(r === 5, "new-throw") }
132 Promise.accept(5).chain(undefined, assertUnreachable).chain(
133 function(x) { assertAsync(x === 5, "resolved/chain-nohandler") },
140 Promise.reject(5).chain(assertUnreachable, undefined).chain(
142 function(r) { assertAsync(r === 5, "rejected/chain-nohandler") }
148 Promise.accept(5).then(undefined, assertUnreachable).chain(
149 function(x) { assertAsync(x === 5, "resolved/then-nohandler-undefined") },
153 Promise.accept(6).then(null, assertUnreachable).chain(
154 function(x) { assertAsync(x === 6, "resolved/then-nohandler-null") },
161 Promise.reject(5).then(assertUnreachable, undefined).chain(
163 function(r) { assertAsync(r === 5, "rejected/then-nohandler-undefined") }
166 Promise.reject(6).then(assertUnreachable, null).chain(
168 function(r) { assertAsync(r === 6, "rejected/then-nohandler-null") }
174 var p1 = Promise.accept(5)
175 var p2 = Promise.accept(p1)
176 var p3 = Promise.accept(p2)
178 function(x) { assertAsync(x === p2, "resolved/chain") },
185 var p1 = Promise.accept(5)
186 var p2 = Promise.accept(p1)
187 var p3 = Promise.accept(p2)
189 function(x) { assertAsync(x === 5, "resolved/then") },
196 var p1 = Promise.reject(5)
197 var p2 = Promise.accept(p1)
198 var p3 = Promise.accept(p2)
200 function(x) { assertAsync(x === p2, "rejected/chain") },
207 var p1 = Promise.reject(5)
208 var p2 = Promise.accept(p1)
209 var p3 = Promise.accept(p2)
212 function(x) { assertAsync(x === 5, "rejected/then") }
218 var p1 = Promise.accept(5)
219 var p2 = Promise.accept(p1)
220 var p3 = Promise.accept(p2)
221 p3.chain(function(x) { return x }, assertUnreachable).chain(
222 function(x) { assertAsync(x === p1, "resolved/chain/chain") },
229 var p1 = Promise.accept(5)
230 var p2 = Promise.accept(p1)
231 var p3 = Promise.accept(p2)
232 p3.chain(function(x) { return x }, assertUnreachable).then(
233 function(x) { assertAsync(x === 5, "resolved/chain/then") },
240 var p1 = Promise.accept(5)
241 var p2 = Promise.accept(p1)
242 var p3 = Promise.accept(p2)
243 p3.chain(function(x) { return 6 }, assertUnreachable).chain(
244 function(x) { assertAsync(x === 6, "resolved/chain/chain2") },
251 var p1 = Promise.accept(5)
252 var p2 = Promise.accept(p1)
253 var p3 = Promise.accept(p2)
254 p3.chain(function(x) { return 6 }, assertUnreachable).then(
255 function(x) { assertAsync(x === 6, "resolved/chain/then2") },
262 var p1 = Promise.accept(5)
263 var p2 = Promise.accept(p1)
264 var p3 = Promise.accept(p2)
265 p3.then(function(x) { return x + 1 }, assertUnreachable).chain(
266 function(x) { assertAsync(x === 6, "resolved/then/chain") },
273 var p1 = Promise.accept(5)
274 var p2 = Promise.accept(p1)
275 var p3 = Promise.accept(p2)
276 p3.then(function(x) { return x + 1 }, assertUnreachable).then(
277 function(x) { assertAsync(x === 6, "resolved/then/then") },
284 var p1 = Promise.accept(5)
285 var p2 = Promise.accept(p1)
286 var p3 = Promise.accept(p2)
287 p3.then(function(x){ return Promise.accept(x+1) }, assertUnreachable).chain(
288 function(x) { assertAsync(x === 6, "resolved/then/chain2") },
295 var p1 = Promise.accept(5)
296 var p2 = Promise.accept(p1)
297 var p3 = Promise.accept(p2)
298 p3.then(function(x) { return Promise.accept(x+1) }, assertUnreachable).then(
299 function(x) { assertAsync(x === 6, "resolved/then/then2") },
306 var p1 = Promise.accept(5)
307 var p2 = Promise.accept(p1)
308 var p3 = Promise.accept(p2)
309 p3.chain(function(x) { throw 6 }, assertUnreachable).chain(
311 function(x) { assertAsync(x === 6, "resolved/chain-throw/chain") }
317 var p1 = Promise.accept(5)
318 var p2 = Promise.accept(p1)
319 var p3 = Promise.accept(p2)
320 p3.chain(function(x) { throw 6 }, assertUnreachable).then(
322 function(x) { assertAsync(x === 6, "resolved/chain-throw/then") }
328 var p1 = Promise.accept(5)
329 var p2 = Promise.accept(p1)
330 var p3 = Promise.accept(p2)
331 p3.then(function(x) { throw 6 }, assertUnreachable).chain(
333 function(x) { assertAsync(x === 6, "resolved/then-throw/chain") }
339 var p1 = Promise.accept(5)
340 var p2 = Promise.accept(p1)
341 var p3 = Promise.accept(p2)
342 p3.then(function(x) { throw 6 }, assertUnreachable).then(
344 function(x) { assertAsync(x === 6, "resolved/then-throw/then") }
350 var p1 = Promise.accept(5)
351 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
352 var p3 = Promise.accept(p2)
354 function(x) { assertAsync(x === p2, "resolved/thenable/chain") },
361 var p1 = Promise.accept(5)
362 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
363 var p3 = Promise.accept(p2)
365 function(x) { assertAsync(x === 5, "resolved/thenable/then") },
372 var p1 = Promise.reject(5)
373 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
374 var p3 = Promise.accept(p2)
376 function(x) { assertAsync(x === p2, "rejected/thenable/chain") },
383 var p1 = Promise.reject(5)
384 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
385 var p3 = Promise.accept(p2)
388 function(x) { assertAsync(x === 5, "rejected/thenable/then") }
394 var deferred = Promise.defer()
395 var p1 = deferred.promise
396 var p2 = Promise.accept(p1)
397 var p3 = Promise.accept(p2)
399 function(x) { assertAsync(x === p2, "chain/resolve") },
407 var deferred = Promise.defer()
408 var p1 = deferred.promise
409 var p2 = Promise.accept(p1)
410 var p3 = Promise.accept(p2)
412 function(x) { assertAsync(x === 5, "then/resolve") },
420 var deferred = Promise.defer()
421 var p1 = deferred.promise
422 var p2 = Promise.accept(p1)
423 var p3 = Promise.accept(p2)
425 function(x) { assertAsync(x === p2, "chain/reject") },
433 var deferred = Promise.defer()
434 var p1 = deferred.promise
435 var p2 = Promise.accept(p1)
436 var p3 = Promise.accept(p2)
439 function(x) { assertAsync(x === 5, "then/reject") }
446 var deferred = Promise.defer()
447 var p1 = deferred.promise
448 var p2 = p1.then(1, 2)
450 function(x) { assertAsync(x === 5, "then/resolve-non-function") },
458 var deferred = Promise.defer()
459 var p1 = deferred.promise
460 var p2 = p1.then(1, 2)
463 function(x) { assertAsync(x === 5, "then/reject-non-function") }
470 var deferred = Promise.defer()
471 var p1 = deferred.promise
472 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
473 var p3 = Promise.accept(p2)
475 function(x) { assertAsync(x === p2, "chain/resolve/thenable") },
483 var deferred = Promise.defer()
484 var p1 = deferred.promise
485 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
486 var p3 = Promise.accept(p2)
488 function(x) { assertAsync(x === 5, "then/resolve/thenable") },
496 var deferred = Promise.defer()
497 var p1 = deferred.promise
498 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
499 var p3 = Promise.accept(p2)
501 function(x) { assertAsync(x === p2, "chain/reject/thenable") },
509 var deferred = Promise.defer()
510 var p1 = deferred.promise
511 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
512 var p3 = Promise.accept(p2)
515 function(x) { assertAsync(x === 5, "then/reject/thenable") }
522 var p1 = Promise.accept(5)
523 var p2 = Promise.accept(p1)
524 var deferred = Promise.defer()
525 var p3 = deferred.promise
527 function(x) { assertAsync(x === p2, "chain/resolve2") },
535 var p1 = Promise.accept(5)
536 var p2 = Promise.accept(p1)
537 var deferred = Promise.defer()
538 var p3 = deferred.promise
540 function(x) { assertAsync(x === 5, "then/resolve2") },
548 var p1 = Promise.accept(5)
549 var p2 = Promise.accept(p1)
550 var deferred = Promise.defer()
551 var p3 = deferred.promise
554 function(x) { assertAsync(x === 5, "chain/reject2") }
561 var p1 = Promise.accept(5)
562 var p2 = Promise.accept(p1)
563 var deferred = Promise.defer()
564 var p3 = deferred.promise
567 function(x) { assertAsync(x === 5, "then/reject2") }
574 var p1 = Promise.accept(5)
575 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
576 var deferred = Promise.defer()
577 var p3 = deferred.promise
579 function(x) { assertAsync(x === p2, "chain/resolve/thenable2") },
587 var p1 = Promise.accept(5)
588 var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
589 var deferred = Promise.defer()
590 var p3 = deferred.promise
592 function(x) { assertAsync(x === 5, "then/resolve/thenable2") },
600 var p1 = Promise.accept(0)
601 var p2 = p1.chain(function(x) { return p2 }, assertUnreachable)
604 function(r) { assertAsync(r instanceof TypeError, "cyclic/chain") }
610 var p1 = Promise.accept(0)
611 var p2 = p1.then(function(x) { return p2 }, assertUnreachable)
614 function(r) { assertAsync(r instanceof TypeError, "cyclic/then") }
620 var deferred = Promise.defer()
621 var p = deferred.promise
624 function(x) { assertAsync(x === p, "cyclic/deferred/chain") },
631 var deferred = Promise.defer()
632 var p = deferred.promise
636 function(r) { assertAsync(r instanceof TypeError, "cyclic/deferred/then") }
642 Promise.all([]).chain(
643 function(x) { assertAsync(x.length === 0, "all/resolve/empty") },
650 function testPromiseAllNonIterable(value) {
651 Promise.all(value).chain(
654 assertAsync(r instanceof TypeError, 'all/non iterable');
658 testPromiseAllNonIterable(null);
659 testPromiseAllNonIterable(undefined);
660 testPromiseAllNonIterable({});
661 testPromiseAllNonIterable(42);
665 var deferred = Promise.defer();
666 var p = deferred.promise;
672 Promise.all(f()).chain(
674 assertAsync(x.length === 3, "all/resolve/iterable");
675 assertAsync(x[0] === 1, "all/resolve/iterable/0");
676 assertAsync(x[1] === 2, "all/resolve/iterable/1");
677 assertAsync(x[2] === 3, "all/resolve/iterable/2");
689 var deferred1 = Promise.defer()
690 var p1 = deferred1.promise
691 var deferred2 = Promise.defer()
692 var p2 = deferred2.promise
693 var deferred3 = Promise.defer()
694 var p3 = deferred3.promise
695 Promise.all([p1, p2, p3]).chain(
697 assertAsync(x.length === 3, "all/resolve")
698 assertAsync(x[0] === 1, "all/resolve/0")
699 assertAsync(x[1] === 2, "all/resolve/1")
700 assertAsync(x[2] === 3, "all/resolve/2")
714 var deferred = Promise.defer()
715 var p1 = deferred.promise
716 var p2 = Promise.accept(2)
717 var p3 = Promise.defer().promise
718 Promise.all([p1, p2, p3]).chain(
726 var deferred1 = Promise.defer()
727 var p1 = deferred1.promise
728 var deferred2 = Promise.defer()
729 var p2 = deferred2.promise
730 var deferred3 = Promise.defer()
731 var p3 = deferred3.promise
732 Promise.all([p1, p2, p3]).chain(
734 function(x) { assertAsync(x === 2, "all/reject") }
748 defineProperty(numberPrototype, symbolIterator, {
750 assertEquals('number', typeof this);
753 assertEquals('number', typeof this);
760 return {value: i++, done: i > n};
768 Promise.all(3).chain(
770 assertAsync(x.length === 3, "all/iterable/number/length");
771 assertAsync(x[0] === 0, "all/iterable/number/0");
772 assertAsync(x[1] === 1, "all/iterable/number/1");
773 assertAsync(x[2] === 2, "all/iterable/number/2");
776 delete numberPrototype[symbolIterator];
778 assertEquals(getCalls, 1);
779 assertEquals(funcCalls, 1);
780 assertEquals(nextCalls, 3 + 1); // + 1 for {done: true}
789 Promise.race([]).chain(
796 var p1 = Promise.accept(1)
797 var p2 = Promise.accept(2)
798 var p3 = Promise.accept(3)
799 Promise.race([p1, p2, p3]).chain(
800 function(x) { assertAsync(x === 1, "resolved/one") },
807 var p1 = Promise.accept(1)
808 var p2 = Promise.accept(2)
809 var p3 = Promise.accept(3)
810 Promise.race([0, p1, p2, p3]).chain(
811 function(x) { assertAsync(x === 0, "resolved-const/one") },
818 var deferred1 = Promise.defer()
819 var p1 = deferred1.promise
820 var deferred2 = Promise.defer()
821 var p2 = deferred2.promise
822 var deferred3 = Promise.defer()
823 var p3 = deferred3.promise
824 Promise.race([p1, p2, p3]).chain(
825 function(x) { assertAsync(x === 3, "one/resolve") },
834 var deferred = Promise.defer()
835 var p1 = deferred.promise
836 var p2 = Promise.accept(2)
837 var p3 = Promise.defer().promise
838 Promise.race([p1, p2, p3]).chain(
839 function(x) { assertAsync(x === 2, "resolved/one") },
847 var deferred1 = Promise.defer()
848 var p1 = deferred1.promise
849 var deferred2 = Promise.defer()
850 var p2 = deferred2.promise
851 var deferred3 = Promise.defer()
852 var p3 = deferred3.promise
853 Promise.race([p1, p2, p3]).chain(
854 function(x) { assertAsync(x === 3, "one/resolve/reject") },
863 var deferred1 = Promise.defer()
864 var p1 = deferred1.promise
865 var deferred2 = Promise.defer()
866 var p2 = deferred2.promise
867 var deferred3 = Promise.defer()
868 var p3 = deferred3.promise
869 Promise.race([p1, p2, p3]).chain(
871 function(x) { assertAsync(x === 3, "one/reject/resolve") }
880 function testPromiseRaceNonIterable(value) {
881 Promise.race(value).chain(
884 assertAsync(r instanceof TypeError, 'race/non iterable');
888 testPromiseRaceNonIterable(null);
889 testPromiseRaceNonIterable(undefined);
890 testPromiseRaceNonIterable({});
891 testPromiseRaceNonIterable(42);
896 var deferred1 = Promise.defer()
897 var p1 = deferred1.promise
898 var deferred2 = Promise.defer()
899 var p2 = deferred2.promise
900 var deferred3 = Promise.defer()
901 var p3 = deferred3.promise
907 Promise.race(f()).chain(
908 function(x) { assertAsync(x === 3, "race/iterable/resolve/reject") },
917 var deferred1 = Promise.defer()
918 var p1 = deferred1.promise
919 var deferred2 = Promise.defer()
920 var p2 = deferred2.promise
921 var deferred3 = Promise.defer()
922 var p3 = deferred3.promise
928 Promise.race(f()).chain(
930 function(x) { assertAsync(x === 3, "race/iterable/reject/resolve") }
942 defineProperty(numberPrototype, symbolIterator, {
944 assertEquals('number', typeof this);
947 assertEquals('number', typeof this);
954 return {value: i++, done: i > n};
962 Promise.race(3).chain(
964 assertAsync(x === 0, "race/iterable/number");
967 delete numberPrototype[symbolIterator];
969 assertEquals(getCalls, 1);
970 assertEquals(funcCalls, 1);
971 assertEquals(nextCalls, 3 + 1); // + 1 for {done: true}
977 function MyPromise(resolver) {
979 var promise = new Promise(function(resolve, reject) {
981 function(x) { log += "x" + x; resolve(x) },
982 function(r) { log += "r" + r; reject(r) }
985 promise.__proto__ = MyPromise.prototype
989 MyPromise.__proto__ = Promise
990 MyPromise.defer = function() {
992 return call(this.__proto__.defer, this)
995 MyPromise.prototype.__proto__ = Promise.prototype
996 MyPromise.prototype.chain = function(resolve, reject) {
998 return call(this.__proto__.__proto__.chain, this, resolve, reject)
1002 var p1 = new MyPromise(function(resolve, reject) { resolve(1) })
1003 var p2 = new MyPromise(function(resolve, reject) { reject(2) })
1004 var d3 = MyPromise.defer()
1005 assertTrue(d3.promise instanceof Promise, "subclass/instance")
1006 assertTrue(d3.promise instanceof MyPromise, "subclass/instance-my3")
1007 assertTrue(log === "nx1nr2dn", "subclass/create")
1010 var p4 = MyPromise.resolve(4)
1011 var p5 = MyPromise.reject(5)
1012 assertTrue(p4 instanceof Promise, "subclass/instance4")
1013 assertTrue(p4 instanceof MyPromise, "subclass/instance-my4")
1014 assertTrue(p5 instanceof Promise, "subclass/instance5")
1015 assertTrue(p5 instanceof MyPromise, "subclass/instance-my5")
1017 assertTrue(log === "nx4nr5x3", "subclass/resolve")
1020 var d6 = MyPromise.defer()
1021 d6.promise.chain(function(x) {
1022 return new Promise(function(resolve) { resolve(x) })
1023 }).chain(function() {})
1025 assertTrue(log === "dncncnx6", "subclass/chain")
1028 Promise.all([11, Promise.accept(12), 13, MyPromise.accept(14), 15, 16])
1029 assertTrue(log === "nx14n", "subclass/all/arg")
1032 MyPromise.all([21, Promise.accept(22), 23, MyPromise.accept(24), 25, 26])
1033 assertTrue(log === "nx24nnx21nnx23nnnx25nnx26n", "subclass/all/self")