123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832 |
- <!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
- -->
- <html>
- <head>
- <title>Basic Promise Test</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- </head>
- <body>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
- <pre id="test">
- <script type="application/javascript"><!--
- function promiseResolve() {
- ok(Promise, "Promise object should exist");
- var promise = new Promise(function(resolve, reject) {
- ok(resolve, "Promise.resolve exists");
- ok(reject, "Promise.reject exists");
- resolve(42);
- }).then(function(what) {
- ok(true, "Then - resolveCb has been called");
- is(what, 42, "ResolveCb received 42");
- runTest();
- }, function() {
- ok(false, "Then - rejectCb has been called");
- runTest();
- });
- }
- function promiseResolveNoArg() {
- var promise = new Promise(function(resolve, reject) {
- ok(resolve, "Promise.resolve exists");
- ok(reject, "Promise.reject exists");
- resolve();
- }).then(function(what) {
- ok(true, "Then - resolveCb has been called");
- is(what, undefined, "ResolveCb received undefined");
- runTest();
- }, function() {
- ok(false, "Then - rejectCb has been called");
- runTest();
- });
- }
- function promiseReject() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- }).then(function(what) {
- ok(false, "Then - resolveCb has been called");
- runTest();
- }, function(what) {
- ok(true, "Then - rejectCb has been called");
- is(what, 42, "RejectCb received 42");
- runTest();
- });
- }
- function promiseRejectNoHandler() {
- // This test only checks that the code that reports unhandled errors in the
- // Promises implementation does not crash or leak.
- var promise = new Promise(function(res, rej) {
- noSuchMethod();
- });
- runTest();
- }
- function promiseRejectNoArg() {
- var promise = new Promise(function(resolve, reject) {
- reject();
- }).then(function(what) {
- ok(false, "Then - resolveCb has been called");
- runTest();
- }, function(what) {
- ok(true, "Then - rejectCb has been called");
- is(what, undefined, "RejectCb received undefined");
- runTest();
- });
- }
- function promiseException() {
- var promise = new Promise(function(resolve, reject) {
- throw 42;
- }).then(function(what) {
- ok(false, "Then - resolveCb has been called");
- runTest();
- }, function(what) {
- ok(true, "Then - rejectCb has been called");
- is(what, 42, "RejectCb received 42");
- runTest();
- });
- }
- function promiseGC() {
- var resolve;
- var promise = new Promise(function(r1, r2) {
- resolve = r1;
- }).then(function(what) {
- ok(true, "Then - promise is still alive");
- runTest();
- });
- promise = null;
- SpecialPowers.gc();
- SpecialPowers.forceGC();
- SpecialPowers.forceCC();
- resolve(42);
- }
- function promiseAsync_TimeoutResolveThen() {
- var handlerExecuted = false;
- setTimeout(function() {
- ok(handlerExecuted, "Handler should have been called before the timeout.");
- // Allow other assertions to run so the test could fail before the next one.
- setTimeout(runTest, 0);
- }, 0);
- Promise.resolve().then(function() {
- handlerExecuted = true;
- });
- ok(!handlerExecuted, "Handlers are not called before 'then' returns.");
- }
- function promiseAsync_ResolveTimeoutThen() {
- var handlerExecuted = false;
- var promise = Promise.resolve();
- setTimeout(function() {
- ok(handlerExecuted, "Handler should have been called before the timeout.");
- // Allow other assertions to run so the test could fail before the next one.
- setTimeout(runTest, 0);
- }, 0);
- promise.then(function() {
- handlerExecuted = true;
- });
- ok(!handlerExecuted, "Handlers are not called before 'then' returns.");
- }
- function promiseAsync_ResolveThenTimeout() {
- var handlerExecuted = false;
- Promise.resolve().then(function() {
- handlerExecuted = true;
- });
- setTimeout(function() {
- ok(handlerExecuted, "Handler should have been called before the timeout.");
- // Allow other assertions to run so the test could fail before the next one.
- setTimeout(runTest, 0);
- }, 0);
- ok(!handlerExecuted, "Handlers are not called before 'then' returns.");
- }
- function promiseAsync_SyncXHR()
- {
- var handlerExecuted = false;
- Promise.resolve().then(function() {
- handlerExecuted = true;
- // Allow other assertions to run so the test could fail before the next one.
- setTimeout(runTest, 0);
- });
- ok(!handlerExecuted, "Handlers are not called until the next microtask.");
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "testXHR.txt", false);
- xhr.send(null);
- todo(!handlerExecuted, "Sync XHR should not trigger microtask execution.");
- }
- function promiseDoubleThen() {
- var steps = 0;
- var promise = new Promise(function(r1, r2) {
- r1(42);
- });
- promise.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 42, "Value == 42");
- steps++;
- }, function(what) {
- ok(false, "Then.reject has been called");
- });
- promise.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(steps, 1, "Then.resolve - step == 1");
- is(what, 42, "Value == 42");
- runTest();
- }, function(what) {
- ok(false, "Then.reject has been called");
- });
- }
- function promiseThenException() {
- var promise = new Promise(function(resolve, reject) {
- resolve(42);
- });
- promise.then(function(what) {
- ok(true, "Then.resolve has been called");
- throw "booh";
- }).catch(function(e) {
- ok(true, "window.onerror has been called!");
- runTest();
- });
- }
- function promiseThenCatchThen() {
- var promise = new Promise(function(resolve, reject) {
- resolve(42);
- });
- var promise2 = promise.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 42, "Value == 42");
- return what + 1;
- }, function(what) {
- ok(false, "Then.reject has been called");
- });
- isnot(promise, promise2, "These 2 promise objs are different");
- promise2.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 43, "Value == 43");
- return what + 1;
- }, function(what) {
- ok(false, "Then.reject has been called");
- }).catch(function() {
- ok(false, "Catch has been called");
- }).then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 44, "Value == 44");
- runTest();
- }, function(what) {
- ok(false, "Then.reject has been called");
- });
- }
- function promiseThenNoArg() {
- var promise = new Promise(function(resolve, reject) {
- resolve(42);
- });
- var clone = promise.then();
- isnot(promise, clone, "These 2 promise objs are different");
- promise.then(function(v) {
- clone.then(function(cv) {
- is(v, cv, "Both resolve to the same value");
- runTest();
- });
- });
- }
- function promiseThenUndefinedResolveFunction() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- try {
- promise.then(undefined, function(v) {
- is(v, 42, "Promise rejected with 42");
- runTest();
- });
- } catch (e) {
- ok(false, "then should not throw on undefined resolve function");
- }
- }
- function promiseThenNullResolveFunction() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- try {
- promise.then(null, function(v) {
- is(v, 42, "Promise rejected with 42");
- runTest();
- });
- } catch (e) {
- ok(false, "then should not throw on null resolve function");
- }
- }
- function promiseRejectThenCatchThen() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- var promise2 = promise.then(function(what) {
- ok(false, "Then.resolve has been called");
- }, function(what) {
- ok(true, "Then.reject has been called");
- is(what, 42, "Value == 42");
- return what + 1;
- });
- isnot(promise, promise2, "These 2 promise objs are different");
- promise2.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 43, "Value == 43");
- return what+1;
- }).catch(function(what) {
- ok(false, "Catch has been called");
- }).then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 44, "Value == 44");
- runTest();
- });
- }
- function promiseRejectThenCatchThen2() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- promise.then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 42, "Value == 42");
- return what+1;
- }).catch(function(what) {
- is(what, 42, "Value == 42");
- ok(true, "Catch has been called");
- return what+1;
- }).then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 43, "Value == 43");
- runTest();
- });
- }
- function promiseRejectThenCatchExceptionThen() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- promise.then(function(what) {
- ok(false, "Then.resolve has been called");
- }, function(what) {
- ok(true, "Then.reject has been called");
- is(what, 42, "Value == 42");
- throw(what + 1);
- }).catch(function(what) {
- ok(true, "Catch has been called");
- is(what, 43, "Value == 43");
- return what + 1;
- }).then(function(what) {
- ok(true, "Then.resolve has been called");
- is(what, 44, "Value == 44");
- runTest();
- });
- }
- function promiseThenCatchOrderingResolve() {
- var global = 0;
- var f = new Promise(function(r1, r2) {
- r1(42);
- });
- f.then(function() {
- f.then(function() {
- global++;
- });
- f.catch(function() {
- global++;
- });
- f.then(function() {
- global++;
- });
- setTimeout(function() {
- is(global, 2, "Many steps... should return 2");
- runTest();
- }, 0);
- });
- }
- function promiseThenCatchOrderingReject() {
- var global = 0;
- var f = new Promise(function(r1, r2) {
- r2(42);
- })
- f.then(function() {}, function() {
- f.then(function() {
- global++;
- });
- f.catch(function() {
- global++;
- });
- f.then(function() {}, function() {
- global++;
- });
- setTimeout(function() {
- is(global, 2, "Many steps... should return 2");
- runTest();
- }, 0);
- });
- }
- function promiseCatchNoArg() {
- var promise = new Promise(function(resolve, reject) {
- reject(42);
- });
- var clone = promise.catch();
- isnot(promise, clone, "These 2 promise objs are different");
- promise.catch(function(v) {
- clone.catch(function(cv) {
- is(v, cv, "Both reject to the same value");
- runTest();
- });
- });
- }
- function promiseNestedPromise() {
- new Promise(function(resolve, reject) {
- resolve(new Promise(function(resolve, reject) {
- ok(true, "Nested promise is executed");
- resolve(42);
- }));
- }).then(function(value) {
- is(value, 42, "Nested promise is executed and then == 42");
- runTest();
- });
- }
- function promiseNestedNestedPromise() {
- new Promise(function(resolve, reject) {
- resolve(new Promise(function(resolve, reject) {
- ok(true, "Nested promise is executed");
- resolve(42);
- }).then(function(what) { return what+1; }));
- }).then(function(value) {
- is(value, 43, "Nested promise is executed and then == 43");
- runTest();
- });
- }
- function promiseWrongNestedPromise() {
- new Promise(function(resolve, reject) {
- resolve(new Promise(function(r, r2) {
- ok(true, "Nested promise is executed");
- r(42);
- }));
- reject(42);
- }).then(function(value) {
- is(value, 42, "Nested promise is executed and then == 42");
- runTest();
- }, function(value) {
- ok(false, "This is wrong");
- });
- }
- function promiseLoop() {
- new Promise(function(resolve, reject) {
- resolve(new Promise(function(r1, r2) {
- ok(true, "Nested promise is executed");
- r1(new Promise(function(r1, r2) {
- ok(true, "Nested nested promise is executed");
- r1(42);
- }));
- }));
- }).then(function(value) {
- is(value, 42, "Nested nested promise is executed and then == 42");
- runTest();
- }, function(value) {
- ok(false, "This is wrong");
- });
- }
- function promiseStaticReject() {
- var promise = Promise.reject(42).then(function(what) {
- ok(false, "This should not be called");
- }, function(what) {
- is(what, 42, "Value == 42");
- runTest();
- });
- }
- function promiseStaticResolve() {
- var promise = Promise.resolve(42).then(function(what) {
- is(what, 42, "Value == 42");
- runTest();
- }, function() {
- ok(false, "This should not be called");
- });
- }
- function promiseResolveNestedPromise() {
- var promise = Promise.resolve(new Promise(function(r, r2) {
- ok(true, "Nested promise is executed");
- r(42);
- }, function() {
- ok(false, "This should not be called");
- })).then(function(what) {
- is(what, 42, "Value == 42");
- runTest();
- }, function() {
- ok(false, "This should not be called");
- });
- }
- function promiseSimpleThenableResolve() {
- var thenable = { then: function(resolve) { resolve(5); } };
- var promise = new Promise(function(resolve, reject) {
- resolve(thenable);
- });
- promise.then(function(v) {
- ok(v === 5, "promiseSimpleThenableResolve");
- runTest();
- }, function(e) {
- ok(false, "promiseSimpleThenableResolve: Should not reject");
- });
- }
- function promiseSimpleThenableReject() {
- var thenable = { then: function(resolve, reject) { reject(5); } };
- var promise = new Promise(function(resolve, reject) {
- resolve(thenable);
- });
- promise.then(function() {
- ok(false, "promiseSimpleThenableReject: Should not resolve");
- runTest();
- }, function(e) {
- ok(e === 5, "promiseSimpleThenableReject");
- runTest();
- });
- }
- function promiseThenableThrowsBeforeCallback() {
- var thenable = { then: function(resolve) {
- throw new TypeError("Hi there");
- resolve(5);
- }};
- var promise = Promise.resolve(thenable);
- promise.then(function(v) {
- ok(false, "promiseThenableThrowsBeforeCallback: Should've rejected");
- runTest();
- }, function(e) {
- ok(e instanceof TypeError, "promiseThenableThrowsBeforeCallback");
- runTest();
- });
- }
- function promiseThenableThrowsAfterCallback() {
- var thenable = { then: function(resolve) {
- resolve(5);
- throw new TypeError("Hi there");
- }};
- var promise = Promise.resolve(thenable);
- promise.then(function(v) {
- ok(v === 5, "promiseThenableThrowsAfterCallback");
- runTest();
- }, function(e) {
- ok(false, "promiseThenableThrowsAfterCallback: Should've resolved");
- runTest();
- });
- }
- function promiseThenableRejectThenResolve() {
- var thenable = { then: function(resolve, reject) {
- reject(new TypeError("Hi there"));
- resolve(5);
- }};
- var promise = Promise.resolve(thenable);
- promise.then(function(v) {
- ok(false, "promiseThenableRejectThenResolve should have rejected");
- runTest();
- }, function(e) {
- ok(e instanceof TypeError, "promiseThenableRejectThenResolve");
- runTest();
- });
- }
- function promiseWithThenReplaced() {
- // Ensure that we call the 'then' on the promise and not the internal then.
- var promise = new Promise(function(resolve, reject) {
- resolve(5);
- });
- // Rogue `then` always rejects.
- promise.then = function(onFulfill, onReject) {
- onReject(new TypeError("Foo"));
- }
- var promise2 = Promise.resolve(promise);
- promise2.then(function(v) {
- ok(false, "promiseWithThenReplaced: Should've rejected");
- runTest();
- }, function(e) {
- ok(e instanceof TypeError, "promiseWithThenReplaced");
- runTest();
- });
- }
- function promiseStrictHandlers() {
- var promise = Promise.resolve(5);
- promise.then(function() {
- "use strict";
- ok(this === undefined, "Strict mode callback should have this === undefined.");
- runTest();
- });
- }
- function promiseStrictExecutorThisArg() {
- var promise = new Promise(function(resolve, reject) {
- "use strict";
- ok(this === undefined, "thisArg should be undefined.");
- runTest();
- });
- }
- function promiseResolveArray() {
- var p = Promise.resolve([1,2,3]);
- ok(p instanceof Promise, "Should return a Promise.");
- p.then(function(v) {
- ok(Array.isArray(v), "Resolved value should be an Array");
- is(v.length, 3, "Length should match");
- is(v[0], 1, "Resolved value should match original");
- is(v[1], 2, "Resolved value should match original");
- is(v[2], 3, "Resolved value should match original");
- runTest();
- });
- }
- function promiseResolveThenable() {
- var p = Promise.resolve({ then: function(onFulfill, onReject) { onFulfill(2); } });
- ok(p instanceof Promise, "Should cast to a Promise.");
- p.then(function(v) {
- is(v, 2, "Should resolve to 2.");
- runTest();
- }, function(e) {
- ok(false, "promiseResolveThenable should've resolved");
- runTest();
- });
- }
- function promiseResolvePromise() {
- var original = Promise.resolve(true);
- var cast = Promise.resolve(original);
- ok(cast instanceof Promise, "Should cast to a Promise.");
- is(cast, original, "Should return original Promise.");
- cast.then(function(v) {
- is(v, true, "Should resolve to true.");
- runTest();
- });
- }
- // Bug 1009569.
- // Ensure that thenables are run on a clean stack asynchronously.
- // Test case adopted from
- // https://gist.github.com/getify/d64bb01751b50ed6b281#file-bug1-js.
- function promiseResolveThenableCleanStack() {
- function immed(s) { x++; s(); }
- function incX(){ x++; }
- var x = 0;
- var thenable = { then: immed };
- var results = [];
- var p = Promise.resolve(thenable).then(incX);
- results.push(x);
- // check what happens after all "next cycle" steps
- // have had a chance to complete
- setTimeout(function(){
- // Result should be [0, 2] since `thenable` will be called async.
- is(results[0], 0, "Expected thenable to be called asynchronously");
- // See Bug 1023547 comment 13 for why this check has to be gated on p.
- p.then(function() {
- results.push(x);
- is(results[1], 2, "Expected thenable to be called asynchronously");
- runTest();
- });
- },1000);
- }
- // Bug 1008467 - Promise fails with "too much recursion".
- // The bug was that the callbacks passed to a thenable would resolve the
- // promise synchronously when the fulfill handler returned a non-thenable.
- //
- // For example:
- // var p = new Promise(function(resolve) {
- // resolve(5);
- // });
- // var m = Promise.resolve(p);
- //
- // At this point `m` is a Promise that is resolved with a thenable `p`, so it
- // calls `p.then()` with two callbacks, both of which would synchronously resolve
- // `m` when `p` invoked them (on account of itself being resolved, possibly
- // synchronously. A chain of these 'Promise resolved by a Promise' would lead to
- // stack overflow.
- function promiseTestAsyncThenableResolution()
- {
- var k = 3000;
- Promise.resolve().then(function next() {
- k--;
- if (k > 0) return Promise.resolve().then(next);
- }).then(function () {
- ok(true, "Resolution of a chain of thenables should not be synchronous.");
- runTest();
- });
- }
- // Bug 1062323
- function promiseWrapperAsyncResolution()
- {
- var p = new Promise(function(resolve, reject){
- resolve();
- });
- var results = [];
- var q = p.then(function () {
- results.push("1-1");
- }).then(function () {
- results.push("1-2");
- }).then(function () {
- results.push("1-3");
- });
- var r = p.then(function () {
- results.push("2-1");
- }).then(function () {
- results.push("2-2");
- }).then(function () {
- results.push("2-3");
- });
- Promise.all([q, r]).then(function() {
- var match = results[0] == "1-1" &&
- results[1] == "2-1" &&
- results[2] == "1-2" &&
- results[3] == "2-2" &&
- results[4] == "1-3" &&
- results[5] == "2-3";
- info(results);
- ok(match, "Chained promises should resolve asynchronously.");
- runTest();
- }, function() {
- ok(false, "promiseWrapperAsyncResolution: One of the promises failed.");
- runTest();
- });
- }
- var tests = [ promiseResolve, promiseReject,
- promiseException, promiseGC,
- promiseAsync_TimeoutResolveThen,
- promiseAsync_ResolveTimeoutThen,
- promiseAsync_ResolveThenTimeout,
- promiseAsync_SyncXHR,
- promiseDoubleThen, promiseThenException,
- promiseThenCatchThen, promiseRejectThenCatchThen,
- promiseRejectThenCatchThen2,
- promiseRejectThenCatchExceptionThen,
- promiseThenCatchOrderingResolve,
- promiseThenCatchOrderingReject,
- promiseNestedPromise, promiseNestedNestedPromise,
- promiseWrongNestedPromise, promiseLoop,
- promiseStaticReject, promiseStaticResolve,
- promiseResolveNestedPromise,
- promiseResolveNoArg,
- promiseRejectNoArg,
- promiseThenNoArg,
- promiseThenUndefinedResolveFunction,
- promiseThenNullResolveFunction,
- promiseCatchNoArg,
- promiseRejectNoHandler,
- promiseSimpleThenableResolve,
- promiseSimpleThenableReject,
- promiseThenableThrowsBeforeCallback,
- promiseThenableThrowsAfterCallback,
- promiseThenableRejectThenResolve,
- promiseWithThenReplaced,
- promiseStrictHandlers,
- promiseStrictExecutorThisArg,
- promiseResolveArray,
- promiseResolveThenable,
- promiseResolvePromise,
- promiseResolveThenableCleanStack,
- promiseTestAsyncThenableResolution,
- promiseWrapperAsyncResolution,
- ];
- function runTest() {
- if (!tests.length) {
- SimpleTest.finish();
- return;
- }
- var test = tests.shift();
- test();
- }
- SimpleTest.waitForExplicitFinish();
- SimpleTest.requestFlakyTimeout("untriaged");
- runTest();
- // -->
- </script>
- </pre>
- </body>
- </html>
|