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
4// met:
5//
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.
15//
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.
27
28// Flags: --allow-natives-syntax
29
30// Make sure we don't rely on functions patchable by monkeys.
31var call = Function.prototype.call.call.bind(Function.prototype.call)
32var observe = Object.observe;
33var getOwnPropertyNames = Object.getOwnPropertyNames
34var defineProperty = Object.defineProperty
35
36function clear(o) {
37  if (o === null || (typeof o !== 'object' && typeof o !== 'function')) return
38  clear(o.__proto__)
39  var properties = getOwnPropertyNames(o)
40  for (var i in properties) {
41    clearProp(o, properties[i])
42  }
43}
44
45function clearProp(o, name) {
46  var poisoned = {caller: 0, callee: 0, arguments: 0}
47  try {
48    var x = o[name]
49    o[name] = undefined
50    clear(x)
51  } catch(e) {} // assertTrue(name in poisoned) }
52}
53
54// Find intrinsics and null them out.
55var globals = Object.getOwnPropertyNames(this)
56var whitelist = {Promise: true, TypeError: true}
57for (var i in globals) {
58  var name = globals[i]
59  if (name in whitelist || name[0] === name[0].toLowerCase()) delete globals[i]
60}
61for (var i in globals) {
62  if (globals[i]) clearProp(this, globals[i])
63}
64
65
66var asyncAssertsExpected = 0;
67
68function assertAsyncRan() { ++asyncAssertsExpected }
69
70function assertAsync(b, s) {
71  if (b) {
72    print(s, "succeeded")
73  } else {
74    %AbortJS(s + " FAILED!")  // Simply throwing here will have no effect.
75  }
76  --asyncAssertsExpected
77}
78
79function assertAsyncDone(iteration) {
80  var iteration = iteration || 0
81  var dummy = {}
82  observe(dummy,
83    function() {
84      if (asyncAssertsExpected === 0)
85        assertAsync(true, "all")
86      else if (iteration > 10)  // Shouldn't take more.
87        assertAsync(false, "all")
88      else
89        assertAsyncDone(iteration + 1)
90    }
91  )
92  dummy.dummy = dummy
93}
94
95
96(function() {
97  assertThrows(function() { Promise(function() {}) }, TypeError)
98})();
99
100(function() {
101  assertTrue(new Promise(function() {}) instanceof Promise)
102})();
103
104(function() {
105  assertThrows(function() { new Promise(5) }, TypeError)
106})();
107
108(function() {
109  assertDoesNotThrow(function() { new Promise(function() { throw 5 }) })
110})();
111
112(function() {
113  (new Promise(function() { throw 5 })).chain(
114    assertUnreachable,
115    function(r) { assertAsync(r === 5, "new-throw") }
116  )
117  assertAsyncRan()
118})();
119
120(function() {
121  Promise.accept(5);
122  Promise.accept(5).chain(undefined, assertUnreachable).chain(
123    function(x) { assertAsync(x === 5, "resolved/chain-nohandler") },
124    assertUnreachable
125  )
126  assertAsyncRan()
127})();
128
129(function() {
130  Promise.reject(5).chain(assertUnreachable, undefined).chain(
131    assertUnreachable,
132    function(r) { assertAsync(r === 5, "rejected/chain-nohandler") }
133  )
134  assertAsyncRan()
135})();
136
137(function() {
138  Promise.accept(5).then(undefined, assertUnreachable).chain(
139    function(x) { assertAsync(x === 5, "resolved/then-nohandler-undefined") },
140    assertUnreachable
141  )
142  assertAsyncRan()
143  Promise.accept(6).then(null, assertUnreachable).chain(
144    function(x) { assertAsync(x === 6, "resolved/then-nohandler-null") },
145    assertUnreachable
146  )
147  assertAsyncRan()
148})();
149
150(function() {
151  Promise.reject(5).then(assertUnreachable, undefined).chain(
152    assertUnreachable,
153    function(r) { assertAsync(r === 5, "rejected/then-nohandler-undefined") }
154  )
155  assertAsyncRan()
156  Promise.reject(6).then(assertUnreachable, null).chain(
157    assertUnreachable,
158    function(r) { assertAsync(r === 6, "rejected/then-nohandler-null") }
159  )
160  assertAsyncRan()
161})();
162
163(function() {
164  var p1 = Promise.accept(5)
165  var p2 = Promise.accept(p1)
166  var p3 = Promise.accept(p2)
167  p3.chain(
168    function(x) { assertAsync(x === p2, "resolved/chain") },
169    assertUnreachable
170  )
171  assertAsyncRan()
172})();
173
174(function() {
175  var p1 = Promise.accept(5)
176  var p2 = Promise.accept(p1)
177  var p3 = Promise.accept(p2)
178  p3.then(
179    function(x) { assertAsync(x === 5, "resolved/then") },
180    assertUnreachable
181  )
182  assertAsyncRan()
183})();
184
185(function() {
186  var p1 = Promise.reject(5)
187  var p2 = Promise.accept(p1)
188  var p3 = Promise.accept(p2)
189  p3.chain(
190    function(x) { assertAsync(x === p2, "rejected/chain") },
191    assertUnreachable
192  )
193  assertAsyncRan()
194})();
195
196(function() {
197  var p1 = Promise.reject(5)
198  var p2 = Promise.accept(p1)
199  var p3 = Promise.accept(p2)
200  p3.then(
201    assertUnreachable,
202    function(x) { assertAsync(x === 5, "rejected/then") }
203  )
204  assertAsyncRan()
205})();
206
207(function() {
208  var p1 = Promise.accept(5)
209  var p2 = Promise.accept(p1)
210  var p3 = Promise.accept(p2)
211  p3.chain(function(x) { return x }, assertUnreachable).chain(
212    function(x) { assertAsync(x === p1, "resolved/chain/chain") },
213    assertUnreachable
214  )
215  assertAsyncRan()
216})();
217
218(function() {
219  var p1 = Promise.accept(5)
220  var p2 = Promise.accept(p1)
221  var p3 = Promise.accept(p2)
222  p3.chain(function(x) { return x }, assertUnreachable).then(
223    function(x) { assertAsync(x === 5, "resolved/chain/then") },
224    assertUnreachable
225  )
226  assertAsyncRan()
227})();
228
229(function() {
230  var p1 = Promise.accept(5)
231  var p2 = Promise.accept(p1)
232  var p3 = Promise.accept(p2)
233  p3.chain(function(x) { return 6 }, assertUnreachable).chain(
234    function(x) { assertAsync(x === 6, "resolved/chain/chain2") },
235    assertUnreachable
236  )
237  assertAsyncRan()
238})();
239
240(function() {
241  var p1 = Promise.accept(5)
242  var p2 = Promise.accept(p1)
243  var p3 = Promise.accept(p2)
244  p3.chain(function(x) { return 6 }, assertUnreachable).then(
245    function(x) { assertAsync(x === 6, "resolved/chain/then2") },
246    assertUnreachable
247  )
248  assertAsyncRan()
249})();
250
251(function() {
252  var p1 = Promise.accept(5)
253  var p2 = Promise.accept(p1)
254  var p3 = Promise.accept(p2)
255  p3.then(function(x) { return x + 1 }, assertUnreachable).chain(
256    function(x) { assertAsync(x === 6, "resolved/then/chain") },
257    assertUnreachable
258  )
259  assertAsyncRan()
260})();
261
262(function() {
263  var p1 = Promise.accept(5)
264  var p2 = Promise.accept(p1)
265  var p3 = Promise.accept(p2)
266  p3.then(function(x) { return x + 1 }, assertUnreachable).then(
267    function(x) { assertAsync(x === 6, "resolved/then/then") },
268    assertUnreachable
269  )
270  assertAsyncRan()
271})();
272
273(function() {
274  var p1 = Promise.accept(5)
275  var p2 = Promise.accept(p1)
276  var p3 = Promise.accept(p2)
277  p3.then(function(x){ return Promise.accept(x+1) }, assertUnreachable).chain(
278    function(x) { assertAsync(x === 6, "resolved/then/chain2") },
279    assertUnreachable
280  )
281  assertAsyncRan()
282})();
283
284(function() {
285  var p1 = Promise.accept(5)
286  var p2 = Promise.accept(p1)
287  var p3 = Promise.accept(p2)
288  p3.then(function(x) { return Promise.accept(x+1) }, assertUnreachable).then(
289    function(x) { assertAsync(x === 6, "resolved/then/then2") },
290    assertUnreachable
291  )
292  assertAsyncRan()
293})();
294
295(function() {
296  var p1 = Promise.accept(5)
297  var p2 = Promise.accept(p1)
298  var p3 = Promise.accept(p2)
299  p3.chain(function(x) { throw 6 }, assertUnreachable).chain(
300    assertUnreachable,
301    function(x) { assertAsync(x === 6, "resolved/chain-throw/chain") }
302  )
303  assertAsyncRan()
304})();
305
306(function() {
307  var p1 = Promise.accept(5)
308  var p2 = Promise.accept(p1)
309  var p3 = Promise.accept(p2)
310  p3.chain(function(x) { throw 6 }, assertUnreachable).then(
311    assertUnreachable,
312    function(x) { assertAsync(x === 6, "resolved/chain-throw/then") }
313  )
314  assertAsyncRan()
315})();
316
317(function() {
318  var p1 = Promise.accept(5)
319  var p2 = Promise.accept(p1)
320  var p3 = Promise.accept(p2)
321  p3.then(function(x) { throw 6 }, assertUnreachable).chain(
322    assertUnreachable,
323    function(x) { assertAsync(x === 6, "resolved/then-throw/chain") }
324  )
325  assertAsyncRan()
326})();
327
328(function() {
329  var p1 = Promise.accept(5)
330  var p2 = Promise.accept(p1)
331  var p3 = Promise.accept(p2)
332  p3.then(function(x) { throw 6 }, assertUnreachable).then(
333    assertUnreachable,
334    function(x) { assertAsync(x === 6, "resolved/then-throw/then") }
335  )
336  assertAsyncRan()
337})();
338
339(function() {
340  var p1 = Promise.accept(5)
341  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
342  var p3 = Promise.accept(p2)
343  p3.chain(
344    function(x) { assertAsync(x === p2, "resolved/thenable/chain") },
345    assertUnreachable
346  )
347  assertAsyncRan()
348})();
349
350(function() {
351  var p1 = Promise.accept(5)
352  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
353  var p3 = Promise.accept(p2)
354  p3.then(
355    function(x) { assertAsync(x === 5, "resolved/thenable/then") },
356    assertUnreachable
357  )
358  assertAsyncRan()
359})();
360
361(function() {
362  var p1 = Promise.reject(5)
363  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
364  var p3 = Promise.accept(p2)
365  p3.chain(
366    function(x) { assertAsync(x === p2, "rejected/thenable/chain") },
367    assertUnreachable
368  )
369  assertAsyncRan()
370})();
371
372(function() {
373  var p1 = Promise.reject(5)
374  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
375  var p3 = Promise.accept(p2)
376  p3.then(
377    assertUnreachable,
378    function(x) { assertAsync(x === 5, "rejected/thenable/then") }
379  )
380  assertAsyncRan()
381})();
382
383(function() {
384  var deferred = Promise.defer()
385  var p1 = deferred.promise
386  var p2 = Promise.accept(p1)
387  var p3 = Promise.accept(p2)
388  p3.chain(
389    function(x) { assertAsync(x === p2, "chain/resolve") },
390    assertUnreachable
391  )
392  deferred.resolve(5)
393  assertAsyncRan()
394})();
395
396(function() {
397  var deferred = Promise.defer()
398  var p1 = deferred.promise
399  var p2 = Promise.accept(p1)
400  var p3 = Promise.accept(p2)
401  p3.then(
402    function(x) { assertAsync(x === 5, "then/resolve") },
403    assertUnreachable
404  )
405  deferred.resolve(5)
406  assertAsyncRan()
407})();
408
409(function() {
410  var deferred = Promise.defer()
411  var p1 = deferred.promise
412  var p2 = Promise.accept(p1)
413  var p3 = Promise.accept(p2)
414  p3.chain(
415    function(x) { assertAsync(x === p2, "chain/reject") },
416    assertUnreachable
417  )
418  deferred.reject(5)
419  assertAsyncRan()
420})();
421
422(function() {
423  var deferred = Promise.defer()
424  var p1 = deferred.promise
425  var p2 = Promise.accept(p1)
426  var p3 = Promise.accept(p2)
427  p3.then(
428    assertUnreachable,
429    function(x) { assertAsync(x === 5, "then/reject") }
430  )
431  deferred.reject(5)
432  assertAsyncRan()
433})();
434
435(function() {
436  var deferred = Promise.defer()
437  var p1 = deferred.promise
438  var p2 = p1.then(1, 2)
439  p2.then(
440    function(x) { assertAsync(x === 5, "then/resolve-non-function") },
441    assertUnreachable
442  )
443  deferred.resolve(5)
444  assertAsyncRan()
445})();
446
447(function() {
448  var deferred = Promise.defer()
449  var p1 = deferred.promise
450  var p2 = p1.then(1, 2)
451  p2.then(
452    assertUnreachable,
453    function(x) { assertAsync(x === 5, "then/reject-non-function") }
454  )
455  deferred.reject(5)
456  assertAsyncRan()
457})();
458
459(function() {
460  var deferred = Promise.defer()
461  var p1 = deferred.promise
462  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
463  var p3 = Promise.accept(p2)
464  p3.chain(
465    function(x) { assertAsync(x === p2, "chain/resolve/thenable") },
466    assertUnreachable
467  )
468  deferred.resolve(5)
469  assertAsyncRan()
470})();
471
472(function() {
473  var deferred = Promise.defer()
474  var p1 = deferred.promise
475  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
476  var p3 = Promise.accept(p2)
477  p3.then(
478    function(x) { assertAsync(x === 5, "then/resolve/thenable") },
479    assertUnreachable
480  )
481  deferred.resolve(5)
482  assertAsyncRan()
483})();
484
485(function() {
486  var deferred = Promise.defer()
487  var p1 = deferred.promise
488  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
489  var p3 = Promise.accept(p2)
490  p3.chain(
491    function(x) { assertAsync(x === p2, "chain/reject/thenable") },
492    assertUnreachable
493  )
494  deferred.reject(5)
495  assertAsyncRan()
496})();
497
498(function() {
499  var deferred = Promise.defer()
500  var p1 = deferred.promise
501  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
502  var p3 = Promise.accept(p2)
503  p3.then(
504    assertUnreachable,
505    function(x) { assertAsync(x === 5, "then/reject/thenable") }
506  )
507  deferred.reject(5)
508  assertAsyncRan()
509})();
510
511(function() {
512  var p1 = Promise.accept(5)
513  var p2 = Promise.accept(p1)
514  var deferred = Promise.defer()
515  var p3 = deferred.promise
516  p3.chain(
517    function(x) { assertAsync(x === p2, "chain/resolve2") },
518    assertUnreachable
519  )
520  deferred.resolve(p2)
521  assertAsyncRan()
522})();
523
524(function() {
525  var p1 = Promise.accept(5)
526  var p2 = Promise.accept(p1)
527  var deferred = Promise.defer()
528  var p3 = deferred.promise
529  p3.then(
530    function(x) { assertAsync(x === 5, "then/resolve2") },
531    assertUnreachable
532  )
533  deferred.resolve(p2)
534  assertAsyncRan()
535})();
536
537(function() {
538  var p1 = Promise.accept(5)
539  var p2 = Promise.accept(p1)
540  var deferred = Promise.defer()
541  var p3 = deferred.promise
542  p3.chain(
543    assertUnreachable,
544    function(x) { assertAsync(x === 5, "chain/reject2") }
545  )
546  deferred.reject(5)
547  assertAsyncRan()
548})();
549
550(function() {
551  var p1 = Promise.accept(5)
552  var p2 = Promise.accept(p1)
553  var deferred = Promise.defer()
554  var p3 = deferred.promise
555  p3.then(
556    assertUnreachable,
557    function(x) { assertAsync(x === 5, "then/reject2") }
558  )
559  deferred.reject(5)
560  assertAsyncRan()
561})();
562
563(function() {
564  var p1 = Promise.accept(5)
565  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
566  var deferred = Promise.defer()
567  var p3 = deferred.promise
568  p3.chain(
569    function(x) { assertAsync(x === p2, "chain/resolve/thenable2") },
570    assertUnreachable
571  )
572  deferred.resolve(p2)
573  assertAsyncRan()
574})();
575
576(function() {
577  var p1 = Promise.accept(5)
578  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
579  var deferred = Promise.defer()
580  var p3 = deferred.promise
581  p3.then(
582    function(x) { assertAsync(x === 5, "then/resolve/thenable2") },
583    assertUnreachable
584  )
585  deferred.resolve(p2)
586  assertAsyncRan()
587})();
588
589(function() {
590  var p1 = Promise.accept(0)
591  var p2 = p1.chain(function(x) { return p2 }, assertUnreachable)
592  p2.chain(
593    assertUnreachable,
594    function(r) { assertAsync(r instanceof TypeError, "cyclic/chain") }
595  )
596  assertAsyncRan()
597})();
598
599(function() {
600  var p1 = Promise.accept(0)
601  var p2 = p1.then(function(x) { return p2 }, assertUnreachable)
602  p2.chain(
603    assertUnreachable,
604    function(r) { assertAsync(r instanceof TypeError, "cyclic/then") }
605  )
606  assertAsyncRan()
607})();
608
609(function() {
610  var deferred = Promise.defer()
611  var p = deferred.promise
612  deferred.resolve(p)
613  p.chain(
614    function(x) { assertAsync(x === p, "cyclic/deferred/chain") },
615    assertUnreachable
616  )
617  assertAsyncRan()
618})();
619
620(function() {
621  var deferred = Promise.defer()
622  var p = deferred.promise
623  deferred.resolve(p)
624  p.then(
625    assertUnreachable,
626    function(r) { assertAsync(r instanceof TypeError, "cyclic/deferred/then") }
627  )
628  assertAsyncRan()
629})();
630
631(function() {
632  Promise.all({}).chain(
633    assertUnreachable,
634    function(r) { assertAsync(r instanceof TypeError, "all/no-array") }
635  )
636  assertAsyncRan()
637})();
638
639(function() {
640  Promise.all([]).chain(
641    function(x) { assertAsync(x.length === 0, "all/resolve/empty") },
642    assertUnreachable
643  )
644  assertAsyncRan()
645})();
646
647(function() {
648  var deferred1 = Promise.defer()
649  var p1 = deferred1.promise
650  var deferred2 = Promise.defer()
651  var p2 = deferred2.promise
652  var deferred3 = Promise.defer()
653  var p3 = deferred3.promise
654  Promise.all([p1, p2, p3]).chain(
655    function(x) {
656      assertAsync(x.length === 3, "all/resolve")
657      assertAsync(x[0] === 1, "all/resolve/0")
658      assertAsync(x[1] === 2, "all/resolve/1")
659      assertAsync(x[2] === 3, "all/resolve/2")
660    },
661    assertUnreachable
662  )
663  deferred1.resolve(1)
664  deferred3.resolve(3)
665  deferred2.resolve(2)
666  assertAsyncRan()
667  assertAsyncRan()
668  assertAsyncRan()
669  assertAsyncRan()
670})();
671
672(function() {
673  var deferred = Promise.defer()
674  var p1 = deferred.promise
675  var p2 = Promise.accept(2)
676  var p3 = Promise.defer().promise
677  Promise.all([p1, p2, p3]).chain(
678    assertUnreachable,
679    assertUnreachable
680  )
681  deferred.resolve(1)
682})();
683
684(function() {
685  var deferred1 = Promise.defer()
686  var p1 = deferred1.promise
687  var deferred2 = Promise.defer()
688  var p2 = deferred2.promise
689  var deferred3 = Promise.defer()
690  var p3 = deferred3.promise
691  Promise.all([p1, p2, p3]).chain(
692    assertUnreachable,
693    function(x) { assertAsync(x === 2, "all/reject") }
694  )
695  deferred1.resolve(1)
696  deferred3.resolve(3)
697  deferred2.reject(2)
698  assertAsyncRan()
699})();
700
701(function() {
702  Promise.race([]).chain(
703    assertUnreachable,
704    assertUnreachable
705  )
706})();
707
708(function() {
709  var p1 = Promise.accept(1)
710  var p2 = Promise.accept(2)
711  var p3 = Promise.accept(3)
712  Promise.race([p1, p2, p3]).chain(
713    function(x) { assertAsync(x === 1, "resolved/one") },
714    assertUnreachable
715  )
716  assertAsyncRan()
717})();
718
719(function() {
720  var p1 = Promise.accept(1)
721  var p2 = Promise.accept(2)
722  var p3 = Promise.accept(3)
723  Promise.race([0, p1, p2, p3]).chain(
724    function(x) { assertAsync(x === 0, "resolved-const/one") },
725    assertUnreachable
726  )
727  assertAsyncRan()
728})();
729
730(function() {
731  Promise.race({}).chain(
732    assertUnreachable,
733    function(r) { assertAsync(r instanceof TypeError, "one/no-array") }
734  )
735  assertAsyncRan()
736})();
737
738(function() {
739  var deferred1 = Promise.defer()
740  var p1 = deferred1.promise
741  var deferred2 = Promise.defer()
742  var p2 = deferred2.promise
743  var deferred3 = Promise.defer()
744  var p3 = deferred3.promise
745  Promise.race([p1, p2, p3]).chain(
746    function(x) { assertAsync(x === 3, "one/resolve") },
747    assertUnreachable
748  )
749  deferred3.resolve(3)
750  deferred1.resolve(1)
751  assertAsyncRan()
752})();
753
754(function() {
755  var deferred = Promise.defer()
756  var p1 = deferred.promise
757  var p2 = Promise.accept(2)
758  var p3 = Promise.defer().promise
759  Promise.race([p1, p2, p3]).chain(
760    function(x) { assertAsync(x === 2, "resolved/one") },
761    assertUnreachable
762  )
763  deferred.resolve(1)
764  assertAsyncRan()
765})();
766
767(function() {
768  var deferred1 = Promise.defer()
769  var p1 = deferred1.promise
770  var deferred2 = Promise.defer()
771  var p2 = deferred2.promise
772  var deferred3 = Promise.defer()
773  var p3 = deferred3.promise
774  Promise.race([p1, p2, p3]).chain(
775    function(x) { assertAsync(x === 3, "one/resolve/reject") },
776    assertUnreachable
777  )
778  deferred3.resolve(3)
779  deferred1.reject(1)
780  assertAsyncRan()
781})();
782
783(function() {
784  var deferred1 = Promise.defer()
785  var p1 = deferred1.promise
786  var deferred2 = Promise.defer()
787  var p2 = deferred2.promise
788  var deferred3 = Promise.defer()
789  var p3 = deferred3.promise
790  Promise.race([p1, p2, p3]).chain(
791    assertUnreachable,
792    function(x) { assertAsync(x === 3, "one/reject/resolve") }
793  )
794  deferred3.reject(3)
795  deferred1.resolve(1)
796  assertAsyncRan()
797})();
798
799(function() {
800  var log
801  function MyPromise(resolver) {
802    log += "n"
803    var promise = new Promise(function(resolve, reject) {
804      resolver(
805        function(x) { log += "x" + x; resolve(x) },
806        function(r) { log += "r" + r; reject(r) }
807      )
808    })
809    promise.__proto__ = MyPromise.prototype
810    return promise
811  }
812
813  MyPromise.__proto__ = Promise
814  MyPromise.defer = function() {
815    log += "d"
816    return call(this.__proto__.defer, this)
817  }
818
819  MyPromise.prototype.__proto__ = Promise.prototype
820  MyPromise.prototype.chain = function(resolve, reject) {
821    log += "c"
822    return call(this.__proto__.__proto__.chain, this, resolve, reject)
823  }
824
825  log = ""
826  var p1 = new MyPromise(function(resolve, reject) { resolve(1) })
827  var p2 = new MyPromise(function(resolve, reject) { reject(2) })
828  var d3 = MyPromise.defer()
829  assertTrue(d3.promise instanceof Promise, "subclass/instance")
830  assertTrue(d3.promise instanceof MyPromise, "subclass/instance-my3")
831  assertTrue(log === "nx1nr2dn", "subclass/create")
832
833  log = ""
834  var p4 = MyPromise.resolve(4)
835  var p5 = MyPromise.reject(5)
836  assertTrue(p4 instanceof Promise, "subclass/instance4")
837  assertTrue(p4 instanceof MyPromise, "subclass/instance-my4")
838  assertTrue(p5 instanceof Promise, "subclass/instance5")
839  assertTrue(p5 instanceof MyPromise, "subclass/instance-my5")
840  d3.resolve(3)
841  assertTrue(log === "nx4nr5x3", "subclass/resolve")
842
843  log = ""
844  var d6 = MyPromise.defer()
845  d6.promise.chain(function(x) {
846    return new Promise(function(resolve) { resolve(x) })
847  }).chain(function() {})
848  d6.resolve(6)
849  assertTrue(log === "dncncnx6", "subclass/chain")
850
851  log = ""
852  Promise.all([11, Promise.accept(12), 13, MyPromise.accept(14), 15, 16])
853  assertTrue(log === "nx14n", "subclass/all/arg")
854
855  log = ""
856  MyPromise.all([21, Promise.accept(22), 23, MyPromise.accept(24), 25, 26])
857  assertTrue(log === "nx24nnx21nnx23nnnx25nnx26n", "subclass/all/self")
858})();
859
860
861assertAsyncDone()
862