| Index: test/mjsunit/harmony/promises.js
 | 
| diff --git a/test/mjsunit/harmony/promises.js b/test/mjsunit/harmony/promises.js
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..7371b2c16c32050644ccc46e22617dcfe8d8b2cf
 | 
| --- /dev/null
 | 
| +++ b/test/mjsunit/harmony/promises.js
 | 
| @@ -0,0 +1,723 @@
 | 
| +// Copyright 2013 the V8 project authors. All rights reserved.
 | 
| +// Redistribution and use in source and binary forms, with or without
 | 
| +// modification, are permitted provided that the following conditions are
 | 
| +// met:
 | 
| +//
 | 
| +//     * Redistributions of source code must retain the above copyright
 | 
| +//       notice, this list of conditions and the following disclaimer.
 | 
| +//     * Redistributions in binary form must reproduce the above
 | 
| +//       copyright notice, this list of conditions and the following
 | 
| +//       disclaimer in the documentation and/or other materials provided
 | 
| +//       with the distribution.
 | 
| +//     * Neither the name of Google Inc. nor the names of its
 | 
| +//       contributors may be used to endorse or promote products derived
 | 
| +//       from this software without specific prior written permission.
 | 
| +//
 | 
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
| +
 | 
| +// Flags: --harmony-promises --harmony-observation --allow-natives-syntax
 | 
| +
 | 
| +var asyncAssertsExpected = 0;
 | 
| +
 | 
| +function assertAsyncRan() { ++asyncAssertsExpected }
 | 
| +
 | 
| +function assertAsync(b, s) {
 | 
| +  if (b) {
 | 
| +    print(s, "succeeded")
 | 
| +  } else {
 | 
| +    %AbortJS(s + " FAILED!")  // Simply throwing here will have no effect.
 | 
| +  }
 | 
| +  --asyncAssertsExpected
 | 
| +}
 | 
| +
 | 
| +function assertAsyncDone(iteration) {
 | 
| +  var iteration = iteration || 0
 | 
| +  var dummy = {}
 | 
| +  Object.observe(dummy,
 | 
| +    function() {
 | 
| +      if (asyncAssertsExpected === 0)
 | 
| +        assertAsync(true, "all")
 | 
| +      else if (iteration > 10)  // Shouldn't take more.
 | 
| +        assertAsync(false, "all")
 | 
| +      else
 | 
| +        assertAsyncDone(iteration + 1)
 | 
| +    }
 | 
| +  )
 | 
| +  dummy.dummy = dummy
 | 
| +}
 | 
| +
 | 
| +
 | 
| +(function() {
 | 
| +  Promise.resolved(5);
 | 
| +  Promise.resolved(5).when(undefined, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === undefined, "resolved/when-nohandler") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  Promise.rejected(5).when(assertUnreachable, undefined).when(
 | 
| +    function(x) { assertAsync(x === undefined, "rejected/when-nohandler") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  Promise.resolved(5).then(undefined, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === undefined, "resolved/then-nohandler") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  Promise.rejected(5).then(assertUnreachable, undefined).when(
 | 
| +    function(x) { assertAsync(x === undefined, "rejected/then-nohandler") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "resolved/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "resolved/then") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.rejected(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "rejected/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.rejected(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "rejected/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { return x }, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === p1, "resolved/when/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { return x }, assertUnreachable).then(
 | 
| +    function(x) { assertAsync(x === 5, "resolved/when/then") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { return 6 }, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/when/when2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { return 6 }, assertUnreachable).then(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/when/then2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { return x + 1 }, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { return x + 1 }, assertUnreachable).then(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then/then") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { return Promise.resolved(x+1) }, assertUnreachable).when(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then/when2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { return Promise.resolved(x+1) }, assertUnreachable).then(
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then/then2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { throw 6 }, assertUnreachable).when(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 6, "resolved/when-throw/when") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(function(x) { throw 6 }, assertUnreachable).then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 6, "resolved/when-throw/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { throw 6 }, assertUnreachable).when(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then-throw/when") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(function(x) { throw 6 }, assertUnreachable).then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 6, "resolved/then-throw/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "resolved/thenable/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "resolved/thenable/then") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.rejected(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "rejected/thenable/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.rejected(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "rejected/thenable/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/resolve") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "then/resolve") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/reject") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "then/reject") }
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/resolve/thenable") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "then/resolve/thenable") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/reject/thenable") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var p3 = Promise.resolved(p2)
 | 
| +  p3.then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "then/reject/thenable") }
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/resolve2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(p2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "then/resolve2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(p2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.when(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "when/reject2") }
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = Promise.resolved(p1)
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.then(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 5, "then/reject2") }
 | 
| +  )
 | 
| +  deferred.reject(5)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.when(
 | 
| +    function(x) { assertAsync(x === p2, "when/resolve/thenable2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(p2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(5)
 | 
| +  var p2 = {then: function(onResolve, onReject) { onResolve(p1) }}
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p3 = deferred.promise
 | 
| +  p3.then(
 | 
| +    function(x) { assertAsync(x === 5, "then/resolve/thenable2") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(p2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(0)
 | 
| +  var p2 = p1.when(function(x) { return p2 }, assertUnreachable)
 | 
| +  p2.when(
 | 
| +    assertUnreachable,
 | 
| +    function(r) { assertAsync(r instanceof TypeError, "cyclic/when") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(0)
 | 
| +  var p2 = p1.then(function(x) { return p2 }, assertUnreachable)
 | 
| +  p2.when(
 | 
| +    assertUnreachable,
 | 
| +    function(r) { assertAsync(r instanceof TypeError, "cyclic/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p = deferred.promise
 | 
| +  deferred.resolve(p)
 | 
| +  p.when(
 | 
| +    function(x) { assertAsync(x === p, "cyclic/deferred/when") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p = deferred.promise
 | 
| +  deferred.resolve(p)
 | 
| +  p.then(
 | 
| +    assertUnreachable,
 | 
| +    function(r) { assertAsync(r instanceof TypeError, "cyclic/deferred/then") }
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred1 = Promise.deferred()
 | 
| +  var p1 = deferred1.promise
 | 
| +  var deferred2 = Promise.deferred()
 | 
| +  var p2 = deferred2.promise
 | 
| +  var deferred3 = Promise.deferred()
 | 
| +  var p3 = deferred3.promise
 | 
| +  Promise.all([p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === undefined, "all/resolve") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred1.resolve(1)
 | 
| +  deferred3.resolve(3)
 | 
| +  deferred2.resolve(2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(2)
 | 
| +  var p3 = Promise.deferred().promise
 | 
| +  Promise.all([p1, p2, p3]).when(
 | 
| +    assertUnreachable,
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(1)
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred1 = Promise.deferred()
 | 
| +  var p1 = deferred1.promise
 | 
| +  var deferred2 = Promise.deferred()
 | 
| +  var p2 = deferred2.promise
 | 
| +  var deferred3 = Promise.deferred()
 | 
| +  var p3 = deferred3.promise
 | 
| +  Promise.all([p1, p2, p3]).when(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 2, "all/reject") }
 | 
| +  )
 | 
| +  deferred1.resolve(1)
 | 
| +  deferred3.resolve(3)
 | 
| +  deferred2.reject(2)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(1)
 | 
| +  var p2 = Promise.resolved(2)
 | 
| +  var p3 = Promise.resolved(3)
 | 
| +  Promise.one([p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === 1, "resolved/all") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var p1 = Promise.resolved(1)
 | 
| +  var p2 = Promise.resolved(2)
 | 
| +  var p3 = Promise.resolved(3)
 | 
| +  Promise.one([0, p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === 0, "resolved-const/all") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred1 = Promise.deferred()
 | 
| +  var p1 = deferred1.promise
 | 
| +  var deferred2 = Promise.deferred()
 | 
| +  var p2 = deferred2.promise
 | 
| +  var deferred3 = Promise.deferred()
 | 
| +  var p3 = deferred3.promise
 | 
| +  Promise.one([p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === 3, "one/resolve") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred3.resolve(3)
 | 
| +  deferred1.resolve(1)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred = Promise.deferred()
 | 
| +  var p1 = deferred.promise
 | 
| +  var p2 = Promise.resolved(2)
 | 
| +  var p3 = Promise.deferred().promise
 | 
| +  Promise.one([p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === 2, "resolved/one") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred.resolve(1)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred1 = Promise.deferred()
 | 
| +  var p1 = deferred1.promise
 | 
| +  var deferred2 = Promise.deferred()
 | 
| +  var p2 = deferred2.promise
 | 
| +  var deferred3 = Promise.deferred()
 | 
| +  var p3 = deferred3.promise
 | 
| +  Promise.one([p1, p2, p3]).when(
 | 
| +    function(x) { assertAsync(x === 3, "one/resolve/reject") },
 | 
| +    assertUnreachable
 | 
| +  )
 | 
| +  deferred3.resolve(3)
 | 
| +  deferred1.reject(1)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var deferred1 = Promise.deferred()
 | 
| +  var p1 = deferred1.promise
 | 
| +  var deferred2 = Promise.deferred()
 | 
| +  var p2 = deferred2.promise
 | 
| +  var deferred3 = Promise.deferred()
 | 
| +  var p3 = deferred3.promise
 | 
| +  Promise.one([p1, p2, p3]).when(
 | 
| +    assertUnreachable,
 | 
| +    function(x) { assertAsync(x === 3, "one/reject/resolve") }
 | 
| +  )
 | 
| +  deferred3.reject(3)
 | 
| +  deferred1.resolve(1)
 | 
| +  assertAsyncRan()
 | 
| +})();
 | 
| +
 | 
| +(function() {
 | 
| +  var log
 | 
| +  function MyPromise(resolver) {
 | 
| +    log += "n"
 | 
| +    Promise.call(this,
 | 
| +      function(resolve, reject) {
 | 
| +        resolver(
 | 
| +          function(x) { log += "x" + x; resolve(x) },
 | 
| +          function(r) { log += "r" + r; reject(r) }
 | 
| +        )
 | 
| +      }
 | 
| +    )
 | 
| +  }
 | 
| +
 | 
| +  MyPromise.__proto__ = Promise
 | 
| +  MyPromise.deferred = function() {
 | 
| +    log += "d"
 | 
| +    return this.__proto__.deferred.call(this)
 | 
| +  }
 | 
| +
 | 
| +  MyPromise.prototype.__proto__ = Promise.prototype
 | 
| +  MyPromise.prototype.when = function(resolve, reject) {
 | 
| +    log += "w"
 | 
| +    return this.__proto__.__proto__.when.call(this, resolve, reject)
 | 
| +  }
 | 
| +
 | 
| +  log = ""
 | 
| +  var p1 = new MyPromise(function(resolve, reject) { resolve(1) })
 | 
| +  var p2 = new MyPromise(function(resolve, reject) { reject(2) })
 | 
| +  var d3 = MyPromise.deferred()
 | 
| +  assertTrue(d3.promise instanceof MyPromise, "subclass/instance3")
 | 
| +  assertTrue(log === "nx1nr2dn", "subclass/create")
 | 
| +
 | 
| +  log = ""
 | 
| +  var p4 = MyPromise.resolved(4)
 | 
| +  var p5 = MyPromise.rejected(5)
 | 
| +  assertTrue(p4 instanceof MyPromise, "subclass/instance4")
 | 
| +  assertTrue(p5 instanceof MyPromise, "subclass/instance5")
 | 
| +  d3.resolve(3)
 | 
| +  assertTrue(log === "nx4nr5x3", "subclass/resolve")
 | 
| +
 | 
| +  log = ""
 | 
| +  var d6 = MyPromise.deferred()
 | 
| +  d6.promise.when(function(x) { return new Promise(x) }).when(function() {})
 | 
| +  d6.resolve(6)
 | 
| +  assertTrue(log === "dnwnwnx6", "subclass/when")
 | 
| +
 | 
| +  log = ""
 | 
| +  Promise.all([11, Promise.resolved(12), 13, MyPromise.resolved(14), 15, 16])
 | 
| +  assertTrue(log === "nx14wn", "subclass/all/arg")
 | 
| +
 | 
| +  log = ""
 | 
| +  MyPromise.all([21, Promise.resolved(22), 23, MyPromise.resolved(24), 25, 26])
 | 
| +  assertTrue(log === "nx24dnnx21wnnx23wnwnnx25wnnx26wn", "subclass/all/self")
 | 
| +})();
 | 
| +
 | 
| +
 | 
| +assertAsyncDone()
 | 
| 
 |