/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://moz.org/MPL/2.0/. */ function shouldBe(expected, actual, msg = "") { if (msg) msg = " for " + msg; if (actual !== expected) throw new Error("bad value" + msg + ": " + actual + ". Expected " + expected); } function shouldBeAsync(expected, run, msg) { let actual; var hadError = false; run().then(function(value) { actual = value; }, function(error) { hadError = true; actual = error; }); drainMicrotasks(); if (hadError) throw actual; shouldBe(expected, actual, msg); } function shouldThrow(run, errorType, message) { let actual; var hadError = false; try { actual = run(); } catch (e) { hadError = true; actual = e; } if (!hadError) throw new Error("Expected " + run + "() to throw " + errorType.name + ", but did not throw."); if (!(actual instanceof errorType)) throw new Error("Expeced " + run + "() to throw " + errorType.name + " , but threw '" + actual + "'"); if (message !== void 0 && actual.message !== message) throw new Error("Expected " + run + "() to throw '" + message + "', but threw '" + actual.message + "'"); } function shouldThrowAsync(run, errorType, message) { let actual; var hadError = false; run().then(function(value) { actual = value; }, function(error) { hadError = true; actual = error; }); drainMicrotasks(); if (!hadError) throw new Error("Expected " + run + "() to throw " + errorType.name + ", but did not throw."); if (!(actual instanceof errorType)) throw new Error("Expected " + run + "() to throw " + errorType.name + ", but threw '" + actual + "'"); if (message !== void 0 && actual.message !== message) throw new Error("Expected " + run + "() to throw '" + message + "', but threw '" + actual.message + "'"); } function assert(cond, msg = "") { if (!cond) throw new Error(msg); } function shouldThrowSyntaxError(str, message) { var hadError = false; try { eval(str); } catch (e) { if (e instanceof SyntaxError) { hadError = true; if (typeof message === "string") assert(e.message === message, "Expected '" + message + "' but threw '" + e.message + "'"); } } assert(hadError, "Did not throw syntax error"); } // semantics.js (function mozSemantics() { async function empty() { } async function simpleReturn() { return 1; } async function simpleAwait() { var result = await 2; return result; } async function simpleAwaitAsync() { var result = await simpleReturn(); return 2 + result; } async function returnOtherAsync() { return 1 + await simpleAwaitAsync(); } async function simpleThrower() { throw new Error(); } async function delegatedThrower() { var val = await simpleThrower(); return val; } async function tryCatch() { try { await delegatedThrower(); return 'FAILED'; } catch (_) { return 5; } } async function tryCatchThrow() { try { await delegatedThrower(); return 'FAILED'; } catch (_) { return delegatedThrower(); } } async function wellFinally() { try { await delegatedThrower(); } catch (_) { return 'FAILED'; } finally { return 6; } } async function finallyMayFail() { try { await delegatedThrower(); } catch (_) { return 5; } finally { return delegatedThrower(); } } async function embedded() { async function inner() { return 7; } return await inner(); } // recursion, it works! async function fib(n) { return (n == 0 || n == 1) ? n : await fib(n - 1) + await fib(n - 2); } // mutual recursion async function isOdd(n) { async function isEven(n) { return n === 0 || await isOdd(n - 1); } return n !== 0 && await isEven(n - 1); } // recursion, take three! var hardcoreFib = async function fib2(n) { return (n == 0 || n == 1) ? n : await fib2(n - 1) + await fib2(n - 2); } var asyncExpr = async function() { return 10; } var namedAsyncExpr = async function simple() { return 11; } async function executionOrder() { var value = 0; async function first() { return (value = value === 0 ? 1 : value); } async function second() { return (value = value === 0 ? 2 : value); } async function third() { return (value = value === 0 ? 3 : value); } return await first() + await second() + await third() + 6; } async function miscellaneous() { if (arguments.length === 3 && arguments.callee.name === "miscellaneous") return 14; } function thrower() { throw 15; } async function defaultArgs(arg = thrower()) { } // Async functions are not constructible shouldThrow(() => { async function Person() { } new Person(); }, TypeError); shouldBeAsync(undefined, empty); shouldBeAsync(1, simpleReturn); shouldBeAsync(2, simpleAwait); shouldBeAsync(3, simpleAwaitAsync); shouldBeAsync(4, returnOtherAsync); shouldThrowAsync(simpleThrower, Error); shouldBeAsync(5, tryCatch); shouldBeAsync(6, wellFinally); shouldThrowAsync(finallyMayFail, Error); shouldBeAsync(7, embedded); shouldBeAsync(8, () => fib(6)); shouldBeAsync(9, executionOrder); shouldBeAsync(10, asyncExpr); shouldBeAsync(11, namedAsyncExpr); shouldBeAsync(12, () => isOdd(12).then(v => v ? "oops" : 12)); shouldBeAsync(13, () => hardcoreFib(7)); shouldBeAsync(14, () => miscellaneous(1, 2, 3)); shouldBeAsync(15, () => defaultArgs().catch(e => e)); })(); // methods.js (function mozMethods() { class X { constructor() { this.value = 42; } async getValue() { return this.value; } setValue(value) { this.value = value; } async increment() { var value = await this.getValue(); this.setValue(value + 1); return this.getValue(); } async getBaseClassName() { return 'X'; } static async getStaticValue() { return 44; } } class Y extends X { async getBaseClassName() { return super.getBaseClassName(); } } var objLiteral = { async get() { return 45; }, someStuff: 5 }; var x = new X(); var y = new Y(); shouldBeAsync(42, () => x.getValue()); shouldBeAsync(43, () => x.increment()); shouldBeAsync(44, () => X.getStaticValue()); shouldBeAsync(45, () => objLiteral.get()); shouldBeAsync('X', () => y.getBaseClassName()); })(); (function mozFunctionNameInferrence() { async function test() { } var anon = async function() { } shouldBe("test", test.name); shouldBe("anon", anon.name); })(); (function mozSyntaxErrors() { shouldThrowSyntaxError("'use strict'; async function eval() {}"); shouldThrowSyntaxError("'use strict'; async function arguments() {}"); shouldThrowSyntaxError("async function a(k = super.prop) { }"); shouldThrowSyntaxError("async function a() { super.prop(); }"); shouldThrowSyntaxError("async function a() { super(); }"); shouldThrowSyntaxError("async function a(k = await 3) {}"); })();