123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- function ok(a, msg) {
- dump("OK: " + !!a + " => " + a + " " + msg + "\n");
- postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
- }
- function todo(a, msg) {
- dump("TODO: " + !a + " => " + a + " " + msg + "\n");
- postMessage({type: 'status', status: !a, msg: a + ": " + msg });
- }
- function is(a, b, msg) {
- dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
- postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
- }
- function isnot(a, b, msg) {
- dump("ISNOT: " + (a!==b) + " => " + a + " | " + b + " " + msg + "\n");
- postMessage({type: 'status', status: a !== b, msg: a + " !== " + b + ": " + msg });
- }
- 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 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 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 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 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_SyncXHRAndImportScripts()
- {
- 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);
- ok(!handlerExecuted, "Sync XHR should not trigger microtask execution.");
- importScripts("../../../dom/xhr/tests/relativeLoad_import.js");
- ok(!handlerExecuted, "importScripts 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, "Catch 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 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 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 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 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 promiseUtilitiesDefined() {
- ok(Promise.all, "Promise.all must be defined when Promise is enabled.");
- ok(Promise.race, "Promise.race must be defined when Promise is enabled.");
- runTest();
- }
- function promiseAllArray() {
- var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
- ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
- p.then(function(values) {
- ok(Array.isArray(values), "Resolved value should be an array.");
- is(values.length, 3, "Resolved array length should match iterable's length.");
- is(values[0], 1, "Array values should match.");
- ok(values[1] instanceof Date, "Array values should match.");
- is(values[2], "firefox", "Array values should match.");
- runTest();
- }, function() {
- ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
- runTest();
- });
- }
- function promiseAllWaitsForAllPromises() {
- var arr = [
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 1), 50);
- }),
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 2), 10);
- }),
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, new Promise(function(resolve2) {
- resolve2(3);
- })), 10);
- }),
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 4), 20);
- })
- ];
- var p = Promise.all(arr);
- p.then(function(values) {
- ok(Array.isArray(values), "Resolved value should be an array.");
- is(values.length, 4, "Resolved array length should match iterable's length.");
- is(values[0], 1, "Array values should match.");
- is(values[1], 2, "Array values should match.");
- is(values[2], 3, "Array values should match.");
- is(values[3], 4, "Array values should match.");
- runTest();
- }, function() {
- ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
- runTest();
- });
- }
- function promiseAllRejectFails() {
- var arr = [
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 1), 50);
- }),
- new Promise(function(resolve, reject) {
- setTimeout(reject.bind(undefined, 2), 10);
- }),
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 3), 10);
- }),
- new Promise(function(resolve) {
- setTimeout(resolve.bind(undefined, 4), 20);
- })
- ];
- var p = Promise.all(arr);
- p.then(function(values) {
- ok(false, "Promise.all shouldn't resolve when iterable has rejected Promises.");
- runTest();
- }, function(e) {
- ok(true, "Promise.all should reject when iterable has rejected Promises.");
- is(e, 2, "Rejection value should match.");
- runTest();
- });
- }
- function promiseRaceEmpty() {
- var p = Promise.race([]);
- ok(p instanceof Promise, "Should return a Promise.");
- // An empty race never resolves!
- runTest();
- }
- function promiseRaceValuesArray() {
- var p = Promise.race([true, new Date(), 3]);
- ok(p instanceof Promise, "Should return a Promise.");
- p.then(function(winner) {
- is(winner, true, "First value should win.");
- runTest();
- }, function(err) {
- ok(false, "Should not fail " + err + ".");
- runTest();
- });
- }
- function promiseRacePromiseArray() {
- var arr = [
- new Promise(function(resolve) {
- resolve("first");
- }),
- Promise.resolve("second"),
- new Promise(function() {}),
- new Promise(function(resolve) {
- setTimeout(function() {
- setTimeout(function() {
- resolve("fourth");
- }, 0);
- }, 0);
- }),
- ];
- var p = Promise.race(arr);
- p.then(function(winner) {
- is(winner, "first", "First queued resolution should win the race.");
- runTest();
- });
- }
- function promiseRaceReject() {
- var p = Promise.race([
- Promise.reject(new Error("Fail bad!")),
- new Promise(function(resolve) {
- setTimeout(resolve, 0);
- })
- ]);
- p.then(function() {
- ok(false, "Should not resolve when winning Promise rejected.");
- runTest();
- }, function(e) {
- ok(true, "Should be rejected");
- ok(e instanceof Error, "Should reject with Error.");
- ok(e.message == "Fail bad!", "Message should match.");
- runTest();
- });
- }
- function promiseRaceThrow() {
- var p = Promise.race([
- new Promise(function(resolve) {
- nonExistent();
- }),
- new Promise(function(resolve) {
- setTimeout(resolve, 0);
- })
- ]);
- p.then(function() {
- ok(false, "Should not resolve when winning Promise had an error.");
- runTest();
- }, function(e) {
- ok(true, "Should be rejected");
- ok(e instanceof ReferenceError, "Should reject with ReferenceError for function nonExistent().");
- 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 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";
- ok(match, "Chained promises should resolve asynchronously.");
- runTest();
- }, function() {
- ok(false, "promiseWrapperAsyncResolution: One of the promises failed.");
- runTest();
- });
- }
- var tests = [
- promiseResolve,
- promiseReject,
- promiseException,
- promiseAsync_TimeoutResolveThen,
- promiseAsync_ResolveTimeoutThen,
- promiseAsync_ResolveThenTimeout,
- promiseAsync_SyncXHRAndImportScripts,
- promiseDoubleThen,
- promiseThenException,
- promiseThenCatchThen,
- promiseRejectThenCatchThen,
- promiseRejectThenCatchThen2,
- promiseRejectThenCatchExceptionThen,
- promiseThenCatchOrderingResolve,
- promiseThenCatchOrderingReject,
- promiseNestedPromise,
- promiseNestedNestedPromise,
- promiseWrongNestedPromise,
- promiseLoop,
- promiseStaticReject,
- promiseStaticResolve,
- promiseResolveNestedPromise,
- promiseResolveNoArg,
- promiseRejectNoArg,
- promiseThenNoArg,
- promiseThenUndefinedResolveFunction,
- promiseThenNullResolveFunction,
- promiseCatchNoArg,
- promiseRejectNoHandler,
- promiseUtilitiesDefined,
- promiseAllArray,
- promiseAllWaitsForAllPromises,
- promiseAllRejectFails,
- promiseRaceEmpty,
- promiseRaceValuesArray,
- promiseRacePromiseArray,
- promiseRaceReject,
- promiseRaceThrow,
- promiseResolveArray,
- promiseResolveThenable,
- promiseResolvePromise,
- promiseResolveThenableCleanStack,
- promiseWrapperAsyncResolution,
- ];
- function runTest() {
- if (!tests.length) {
- postMessage({ type: 'finish' });
- return;
- }
- var test = tests.shift();
- test();
- }
- onmessage = function() {
- runTest();
- }
|