summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/async-functions
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/tests/non262/async-functions
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/async-functions')
-rw-r--r--js/src/tests/non262/async-functions/BoundNames.js21
-rw-r--r--js/src/tests/non262/async-functions/EarlyErrors.js51
-rw-r--r--js/src/tests/non262/async-functions/ErrorStack.js103
-rw-r--r--js/src/tests/non262/async-functions/arguments_callee.js31
-rw-r--r--js/src/tests/non262/async-functions/async-contains-unicode-escape.js54
-rw-r--r--js/src/tests/non262/async-functions/async-function-declaration-in-modules.js13
-rw-r--r--js/src/tests/non262/async-functions/async-property-name-error.js21
-rw-r--r--js/src/tests/non262/async-functions/await-error.js16
-rw-r--r--js/src/tests/non262/async-functions/await-in-arrow-parameters.js94
-rw-r--r--js/src/tests/non262/async-functions/await-in-parameters-of-async-func.js67
-rw-r--r--js/src/tests/non262/async-functions/await-newline.js15
-rw-r--r--js/src/tests/non262/async-functions/browser.js0
-rw-r--r--js/src/tests/non262/async-functions/construct-newtarget.js79
-rw-r--r--js/src/tests/non262/async-functions/constructor.js33
-rw-r--r--js/src/tests/non262/async-functions/cover-init-name-syntax.js65
-rw-r--r--js/src/tests/non262/async-functions/create-function-parse-before-getprototype.js19
-rw-r--r--js/src/tests/non262/async-functions/duplicate-__proto__.js22
-rw-r--r--js/src/tests/non262/async-functions/forbidden-as-consequent.js14
-rw-r--r--js/src/tests/non262/async-functions/identity.js14
-rw-r--r--js/src/tests/non262/async-functions/inner-caller.js17
-rw-r--r--js/src/tests/non262/async-functions/length.js12
-rw-r--r--js/src/tests/non262/async-functions/methods.js61
-rw-r--r--js/src/tests/non262/async-functions/no-expression-closure.js17
-rw-r--r--js/src/tests/non262/async-functions/parameters-error-reject-promise.js56
-rw-r--r--js/src/tests/non262/async-functions/properties.js76
-rw-r--r--js/src/tests/non262/async-functions/property.js49
-rw-r--r--js/src/tests/non262/async-functions/semantics.js169
-rw-r--r--js/src/tests/non262/async-functions/shell.js0
-rw-r--r--js/src/tests/non262/async-functions/subclass.js31
-rw-r--r--js/src/tests/non262/async-functions/syntax-arrow.js104
-rw-r--r--js/src/tests/non262/async-functions/syntax-modules.js28
-rw-r--r--js/src/tests/non262/async-functions/syntax.js83
-rw-r--r--js/src/tests/non262/async-functions/toSource.js26
-rw-r--r--js/src/tests/non262/async-functions/toString.js24
-rw-r--r--js/src/tests/non262/async-functions/yield.js71
35 files changed, 1556 insertions, 0 deletions
diff --git a/js/src/tests/non262/async-functions/BoundNames.js b/js/src/tests/non262/async-functions/BoundNames.js
new file mode 100644
index 0000000000..a366334da1
--- /dev/null
+++ b/js/src/tests/non262/async-functions/BoundNames.js
@@ -0,0 +1,21 @@
+var BUGNUMBER = 1185106;
+var summary = "Bound names of async functions";
+
+print(BUGNUMBER + ": " + summary);
+
+async function test() {}
+assertEq(test.name, "test");
+
+var test2 = (async function test2() {});
+assertEq(test2.name, "test2");
+
+var anon = async function() {};
+assertEq(anon.name, "anon");
+
+if (typeof Reflect !== "undefined" && Reflect.parse) {
+ var tree = Reflect.parse("export default async function() {}", { target: "module" });
+ assertEq(tree.body[0].declaration.id.name, "default");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/EarlyErrors.js b/js/src/tests/non262/async-functions/EarlyErrors.js
new file mode 100644
index 0000000000..eeac4b2541
--- /dev/null
+++ b/js/src/tests/non262/async-functions/EarlyErrors.js
@@ -0,0 +1,51 @@
+var BUGNUMBER = 1185106;
+var summary = "EarlyErrors for async function";
+
+print(BUGNUMBER + ": " + summary);
+
+function assertThrowsSE(code) {
+ assertThrowsInstanceOf(() => Reflect.parse(code), SyntaxError);
+}
+
+if (typeof Reflect !== "undefined" && Reflect.parse) {
+ // If FormalParameters Contains AwaitExpression is true.
+ assertThrowsSE("async function a(k = await 3) {}");
+ assertThrowsSE("(async function(k = await 3) {})");
+ assertThrowsSE("(async function a(k = await 3) {})");
+
+ // If BindingIdentifier is `eval` or `arguments`.
+ assertThrowsSE("'use strict'; async function eval() {}");
+ assertThrowsSE("'use strict'; (async function eval() {})");
+
+ assertThrowsSE("'use strict'; async function arguments() {}");
+ assertThrowsSE("'use strict'; (async function arguments() {})");
+
+ // If any element of the BoundNames of FormalParameters also occurs in the
+ // LexicallyDeclaredNames of AsyncFunctionBody.
+ assertThrowsSE("async function a(x) { let x; }");
+ assertThrowsSE("(async function(x) { let x; })");
+ assertThrowsSE("(async function a(x) { let x; })");
+
+ // If FormalParameters contains SuperProperty is true.
+ assertThrowsSE("async function a(k = super.prop) { }");
+ assertThrowsSE("(async function(k = super.prop) {})");
+ assertThrowsSE("(async function a(k = super.prop) {})");
+
+ // If AsyncFunctionBody contains SuperProperty is true.
+ assertThrowsSE("async function a() { super.prop(); }");
+ assertThrowsSE("(async function() { super.prop(); })");
+ assertThrowsSE("(async function a() { super.prop(); })");
+
+ // If FormalParameters contains SuperCall is true.
+ assertThrowsSE("async function a(k = super()) {}");
+ assertThrowsSE("(async function(k = super()) {})");
+ assertThrowsSE("(async function a(k = super()) {})");
+
+ // If AsyncFunctionBody contains SuperCall is true.
+ assertThrowsSE("async function a() { super(); }");
+ assertThrowsSE("(async function() { super(); })");
+ assertThrowsSE("(async function a() { super(); })");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/ErrorStack.js b/js/src/tests/non262/async-functions/ErrorStack.js
new file mode 100644
index 0000000000..9f3adc4f72
--- /dev/null
+++ b/js/src/tests/non262/async-functions/ErrorStack.js
@@ -0,0 +1,103 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1343158;
+var summary = "Error.stack should provide meaningful stack trace in async function";
+
+print(BUGNUMBER + ": " + summary);
+
+let COOKIE = "C0F5DBB89807";
+
+async function thrower() {
+ let stack = new Error().stack; // line 11
+ assertEq(/^thrower@.+ErrorStack.js:11/m.test(stack), true, toMessage(stack));
+ assertEq(/^inner@.+ErrorStack.js:38/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*middle@.+ErrorStack.js:58/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ throw new Error(COOKIE); // line 18
+}
+
+async function inner() {
+ let stack = new Error().stack; // line 22
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^inner@.+ErrorStack.js:22/m.test(stack), true, toMessage(stack));
+ assertEq(/^middle@.+ErrorStack.js:58/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await Promise.resolve(100);
+
+ stack = new Error().stack; // line 31
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^inner@.+ErrorStack.js:31/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*middle@.+ErrorStack.js:58/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await thrower(); // line 38
+}
+
+async function middle() {
+ let stack = new Error().stack; // line 42
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/inner@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^middle@.+ErrorStack.js:42/m.test(stack), true, toMessage(stack));
+ assertEq(/^outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await Promise.resolve(1000);
+
+ stack = new Error().stack; // line 51
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/inner@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^middle@.+ErrorStack.js:51/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await inner(); // line 58
+}
+
+async function outer() {
+ let stack = new Error().stack; // line 62
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/inner@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/middle@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^outer@.+ErrorStack.js:62/m.test(stack), true, toMessage(stack));
+ assertEq(/^@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await Promise.resolve(10000);
+
+ stack = new Error().stack; // line 71
+ assertEq(/thrower@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/inner@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/middle@.+ErrorStack.js/m.test(stack), false, toMessage(stack));
+ assertEq(/^outer@.+ErrorStack.js:71/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+
+ await middle(); // line 78
+}
+
+try {
+ getPromiseResult(outer()); // line 82
+ assertEq(true, false);
+} catch (e) {
+ // Re-throw the exception to log the assertion failure properly.
+ if (!e.message.includes(COOKIE))
+ throw e;
+
+ let stack = e.stack;
+ assertEq(/^thrower@.+ErrorStack.js:18/m.test(stack), true, toMessage(stack));
+ assertEq(/^inner@.+ErrorStack.js:38/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*middle@.+ErrorStack.js:58/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*outer@.+ErrorStack.js:78/m.test(stack), true, toMessage(stack));
+ assertEq(/^async\*@.+ErrorStack.js:82/m.test(stack), true, toMessage(stack));
+}
+
+function toMessage(stack) {
+ // Provide the stack string in the error message for debugging.
+ return `[stack: ${stack.replace(/\n/g, "\\n")}]`;
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/arguments_callee.js b/js/src/tests/non262/async-functions/arguments_callee.js
new file mode 100644
index 0000000000..2a577e0b9d
--- /dev/null
+++ b/js/src/tests/non262/async-functions/arguments_callee.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1185106;
+var summary = "arguments.callee in sloppy mode should return wrapped function";
+
+print(BUGNUMBER + ": " + summary);
+
+async function decl1() {
+ return arguments.callee;
+}
+assertEventuallyEq(decl1(), decl1);
+
+var expr1 = async function foo() {
+ return arguments.callee;
+};
+assertEventuallyEq(expr1(), expr1);
+
+var expr2 = async function() {
+ return arguments.callee;
+};
+assertEventuallyEq(expr2(), expr2);
+
+var obj = {
+ async method1() {
+ return arguments.callee;
+ }
+};
+assertEventuallyEq(obj.method1(), obj.method1);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/async-contains-unicode-escape.js b/js/src/tests/non262/async-functions/async-contains-unicode-escape.js
new file mode 100644
index 0000000000..d53dff696c
--- /dev/null
+++ b/js/src/tests/non262/async-functions/async-contains-unicode-escape.js
@@ -0,0 +1,54 @@
+var BUGNUMBER = 1315815;
+var summary = "async/await containing escapes";
+
+print(BUGNUMBER + ": " + summary);
+
+// Using "eval" as the argument name is fugly, but it means evals below are
+// *direct* evals, and so their effects in the unescaped case won't extend
+// past each separate |test| call (as would happen if we used a different name
+// that made each eval into an indirect eval, affecting code in the global
+// scope).
+function test(code, eval)
+{
+ var unescaped = code.replace("###", "async");
+ var escaped = code.replace("###", "\\u0061");
+
+ assertThrowsInstanceOf(() => eval(escaped), SyntaxError);
+ eval(unescaped);
+}
+
+test("### function f() {}", eval);
+test("var x = ### function f() {}", eval);
+test("### x => {};", eval);
+test("var x = ### x => {}", eval);
+test("### () => {};", eval);
+test("var x = ### () => {}", eval);
+test("### (y) => {};", eval);
+test("var x = ### (y) => {}", eval);
+test("({ ### x() {} })", eval);
+test("var x = ### function f() {}", eval);
+
+if (typeof parseModule === "function")
+ test("export default ### function f() {}", parseModule);
+
+assertThrowsInstanceOf(() => eval("async await => 1;"),
+ SyntaxError);
+assertThrowsInstanceOf(() => eval("async aw\\u0061it => 1;"),
+ SyntaxError);
+
+var async = 0;
+assertEq(\u0061sync, 0);
+
+var obj = { \u0061sync() { return 1; } };
+assertEq(obj.async(), 1);
+
+async = function() { return 42; };
+
+var z = async(obj);
+assertEq(z, 42);
+
+var w = async(obj)=>{};
+assertEq(typeof w, "function");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/async-function-declaration-in-modules.js b/js/src/tests/non262/async-functions/async-function-declaration-in-modules.js
new file mode 100644
index 0000000000..41cc37bf33
--- /dev/null
+++ b/js/src/tests/non262/async-functions/async-function-declaration-in-modules.js
@@ -0,0 +1,13 @@
+// |reftest| module
+
+async function f() {
+ return "success";
+}
+
+var AsyncFunction = (async function(){}).constructor;
+
+assertEq(f instanceof AsyncFunction, true);
+
+f().then(v => {
+ reportCompare("success", v);
+});
diff --git a/js/src/tests/non262/async-functions/async-property-name-error.js b/js/src/tests/non262/async-functions/async-property-name-error.js
new file mode 100644
index 0000000000..926794e5d0
--- /dev/null
+++ b/js/src/tests/non262/async-functions/async-property-name-error.js
@@ -0,0 +1,21 @@
+function assertSyntaxError(code) {
+ assertThrowsInstanceOf(() => { Function(code); }, SyntaxError, "Function:" + code);
+ assertThrowsInstanceOf(() => { eval(code); }, SyntaxError, "eval:" + code);
+ var ieval = eval;
+ assertThrowsInstanceOf(() => { ieval(code); }, SyntaxError, "indirect eval:" + code);
+}
+
+assertSyntaxError(`({async async: 0})`);
+assertSyntaxError(`({async async})`);
+assertSyntaxError(`({async async, })`);
+assertSyntaxError(`({async async = 0} = {})`);
+
+for (let decl of ["var", "let", "const"]) {
+ assertSyntaxError(`${decl} {async async: a} = {}`);
+ assertSyntaxError(`${decl} {async async} = {}`);
+ assertSyntaxError(`${decl} {async async, } = {}`);
+ assertSyntaxError(`${decl} {async async = 0} = {}`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/await-error.js b/js/src/tests/non262/async-functions/await-error.js
new file mode 100644
index 0000000000..6fa6143efc
--- /dev/null
+++ b/js/src/tests/non262/async-functions/await-error.js
@@ -0,0 +1,16 @@
+var BUGNUMBER = 1317153;
+var summary = "await outside of async function should provide better error";
+
+print(BUGNUMBER + ": " + summary);
+
+let caught = false;
+try {
+ eval("await 10");
+} catch(e) {
+ assertEq(e.message.includes("await is only valid in"), true);
+ caught = true;
+}
+assertEq(caught, true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/await-in-arrow-parameters.js b/js/src/tests/non262/async-functions/await-in-arrow-parameters.js
new file mode 100644
index 0000000000..ebb4ea9dac
--- /dev/null
+++ b/js/src/tests/non262/async-functions/await-in-arrow-parameters.js
@@ -0,0 +1,94 @@
+var ieval = eval;
+var AsyncFunction = async function(){}.constructor;
+
+var functionContext = {
+ Function: {
+ constructor: Function,
+ toSourceBody: code => `function f() { ${code} }`,
+ toSourceParameter: code => `function f(x = ${code}) { }`,
+ },
+ AsyncFunction: {
+ constructor: AsyncFunction,
+ toSourceBody: code => `async function f() { ${code} }`,
+ toSourceParameter: code => `async function f(x = ${code}) { }`,
+ },
+};
+
+function assertSyntaxError(kind, code) {
+ var {constructor, toSourceBody, toSourceParameter} = functionContext[kind];
+ var body = toSourceBody(code);
+ var parameter = toSourceParameter(code);
+
+ assertThrowsInstanceOf(() => { constructor(code); }, SyntaxError, constructor.name + ":" + code);
+ assertThrowsInstanceOf(() => { constructor(`x = ${code}`, ""); }, SyntaxError, constructor.name + ":" + code);
+
+ assertThrowsInstanceOf(() => { eval(body); }, SyntaxError, "eval:" + body);
+ assertThrowsInstanceOf(() => { ieval(body); }, SyntaxError, "indirect eval:" + body);
+
+ assertThrowsInstanceOf(() => { eval(parameter); }, SyntaxError, "eval:" + parameter);
+ assertThrowsInstanceOf(() => { ieval(parameter); }, SyntaxError, "indirect eval:" + parameter);
+}
+
+function assertNoSyntaxError(kind, code) {
+ var {constructor, toSourceBody, toSourceParameter} = functionContext[kind];
+ var body = toSourceBody(code);
+ var parameter = toSourceParameter(code);
+
+ constructor(code);
+ constructor(`x = ${code}`, "");
+
+ eval(body);
+ ieval(body);
+
+ eval(parameter);
+ ieval(parameter);
+}
+
+function assertSyntaxErrorAsync(code) {
+ assertNoSyntaxError("Function", code);
+ assertSyntaxError("AsyncFunction", code);
+}
+
+function assertSyntaxErrorBoth(code) {
+ assertSyntaxError("Function", code);
+ assertSyntaxError("AsyncFunction", code);
+}
+
+
+// Bug 1353691
+// |await| expression is invalid in arrow functions in async-context.
+// |await/r/g| first parses as |AwaitExpression RegularExpressionLiteral|, when reparsing the
+// arrow function, it is parsed as |IdentRef DIV IdentRef DIV IdentRef|. We need to ensure in this
+// case, that we still treat |await| as a keyword and hence throw a SyntaxError.
+assertSyntaxErrorAsync("(a = await/r/g) => {}");
+assertSyntaxErrorBoth("async(a = await/r/g) => {}");
+
+// Also applies when nesting arrow functions.
+assertSyntaxErrorAsync("(a = (b = await/r/g) => {}) => {}");
+assertSyntaxErrorBoth("async(a = (b = await/r/g) => {}) => {}");
+assertSyntaxErrorBoth("(a = async(b = await/r/g) => {}) => {}");
+assertSyntaxErrorBoth("async(a = async(b = await/r/g) => {}) => {}");
+
+
+// Bug 1355860
+// |await| cannot be used as rest-binding parameter in arrow functions in async-context.
+assertSyntaxErrorAsync("(...await) => {}");
+assertSyntaxErrorBoth("async(...await) => {}");
+
+assertSyntaxErrorAsync("(a, ...await) => {}");
+assertSyntaxErrorBoth("async(a, ...await) => {}");
+
+// Also test nested arrow functions.
+assertSyntaxErrorAsync("(a = (...await) => {}) => {}");
+assertSyntaxErrorBoth("(a = async(...await) => {}) => {}");
+assertSyntaxErrorBoth("async(a = (...await) => {}) => {}");
+assertSyntaxErrorBoth("async(a = async(...await) => {}) => {}");
+
+assertSyntaxErrorAsync("(a = (b, ...await) => {}) => {}");
+assertSyntaxErrorBoth("(a = async(b, ...await) => {}) => {}");
+assertSyntaxErrorBoth("async(a = (b, ...await) => {}) => {}");
+assertSyntaxErrorBoth("async(a = async(b, ...await) => {}) => {}");
+
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/await-in-parameters-of-async-func.js b/js/src/tests/non262/async-functions/await-in-parameters-of-async-func.js
new file mode 100644
index 0000000000..ef4b84d99b
--- /dev/null
+++ b/js/src/tests/non262/async-functions/await-in-parameters-of-async-func.js
@@ -0,0 +1,67 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ * Contributor:
+ */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1478910;
+var summary = 'JSMSG_AWAIT_IN_PARAMETER error for incomplete await expr in async function/generator parameter';
+
+
+//-----------------------------------------------------------------------------
+test();
+//-----------------------------------------------------------------------------
+
+function test()
+{
+ printBugNumber(BUGNUMBER);
+ printStatus(summary);
+
+ let testAwaitInDefaultExprOfAsyncFunc = (code) => {
+ assertThrowsInstanceOf(() => eval(code), SyntaxError, "await expression can't be used in parameter");
+ };
+
+ let testNoException = (code) => {
+ assertEq(completesNormally(code), true);
+ };
+
+ // https://www.ecma-international.org/ecma-262/9.0/
+
+ // Async Generator Function Definitions : AsyncGeneratorDeclaration & AsyncGeneratorExpression
+ // async function* f() {}
+ // f = async function*() {}
+ testAwaitInDefaultExprOfAsyncFunc("async function* f(a = await) {}");
+ testAwaitInDefaultExprOfAsyncFunc("let f = async function*(a = await) {}");
+
+ testAwaitInDefaultExprOfAsyncFunc("function f(a = async function*(a = await) {}) {}");
+ testAwaitInDefaultExprOfAsyncFunc("function f() { a = async function*(a = await) {}; }");
+
+ testAwaitInDefaultExprOfAsyncFunc("async function* f() { a = async function*(a = await) {}; }");
+ testNoException("async function* f() { let a = function(a = await) {}; }");
+
+ testNoException("async function* f(a = async function*() { await 1; }) {}");
+
+ // Async Function Definitions : AsyncFunctionDeclaration & AsyncFunctionExpression
+ // async function f() {}
+ // f = async function() {}
+ testAwaitInDefaultExprOfAsyncFunc("async function f(a = await) {}");
+ testAwaitInDefaultExprOfAsyncFunc("let f = async function(a = await) {}");
+
+ testAwaitInDefaultExprOfAsyncFunc("function f(a = async function(a = await) {}) {}");
+ testAwaitInDefaultExprOfAsyncFunc("function f() { a = async function(a = await) {}; }");
+
+ testAwaitInDefaultExprOfAsyncFunc("async function f() { a = async function(a = await) {}; }");
+ testNoException("async function f() { let a = function(a = await) {}; }");
+
+ testNoException("async function f(a = async function() { await 1; }) {}");
+
+ // Async Arrow Function Definitions : AsyncArrowFunction
+ // async () => {}
+ testAwaitInDefaultExprOfAsyncFunc("async (a = await) => {}");
+
+ testNoException("async (a = async () => { await 1; }) => {}");
+
+ reportCompare(true, true, summary);
+}
diff --git a/js/src/tests/non262/async-functions/await-newline.js b/js/src/tests/non262/async-functions/await-newline.js
new file mode 100644
index 0000000000..dc42fa481a
--- /dev/null
+++ b/js/src/tests/non262/async-functions/await-newline.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1331009;
+var summary = "Newline is allowed between await and operand";
+
+print(BUGNUMBER + ": " + summary);
+
+var expr = async function foo() {
+ return await
+ 10;
+};
+assertEventuallyEq(expr(), 10);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/browser.js b/js/src/tests/non262/async-functions/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/async-functions/browser.js
diff --git a/js/src/tests/non262/async-functions/construct-newtarget.js b/js/src/tests/non262/async-functions/construct-newtarget.js
new file mode 100644
index 0000000000..7d75d0c939
--- /dev/null
+++ b/js/src/tests/non262/async-functions/construct-newtarget.js
@@ -0,0 +1,79 @@
+/* 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://mozilla.org/MPL/2.0/. */
+
+const AsyncFunction = async function(){}.constructor;
+
+
+// Test subclassing %AsyncFunction% works correctly.
+class MyAsync extends AsyncFunction {}
+
+var fn = new MyAsync();
+assertEq(fn instanceof MyAsync, true);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), MyAsync.prototype);
+
+fn = Reflect.construct(MyAsync, []);
+assertEq(fn instanceof MyAsync, true);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), MyAsync.prototype);
+
+fn = Reflect.construct(MyAsync, [], MyAsync);
+assertEq(fn instanceof MyAsync, true);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), MyAsync.prototype);
+
+fn = Reflect.construct(MyAsync, [], AsyncFunction);
+assertEq(fn instanceof MyAsync, false);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype);
+
+
+// Set a different constructor as NewTarget.
+fn = Reflect.construct(MyAsync, [], Array);
+assertEq(fn instanceof MyAsync, false);
+assertEq(fn instanceof AsyncFunction, false);
+assertEq(Object.getPrototypeOf(fn), Array.prototype);
+
+fn = Reflect.construct(AsyncFunction, [], Array);
+assertEq(fn instanceof AsyncFunction, false);
+assertEq(Object.getPrototypeOf(fn), Array.prototype);
+
+
+// The prototype defaults to %AsyncFunctionPrototype% if null.
+function NewTargetNullPrototype() {}
+NewTargetNullPrototype.prototype = null;
+
+fn = Reflect.construct(AsyncFunction, [], NewTargetNullPrototype);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype);
+
+fn = Reflect.construct(MyAsync, [], NewTargetNullPrototype);
+assertEq(fn instanceof MyAsync, false);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype);
+
+
+// "prototype" property is retrieved exactly once.
+var trapLog = [], getLog = [];
+var ProxiedConstructor = new Proxy(AsyncFunction, new Proxy({
+ get(target, propertyKey, receiver) {
+ getLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}, {
+ get(target, propertyKey, receiver) {
+ trapLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}));
+
+fn = Reflect.construct(AsyncFunction, [], ProxiedConstructor);
+assertEqArray(trapLog, ["get"]);
+assertEqArray(getLog, ["prototype"]);
+assertEq(fn instanceof AsyncFunction, true);
+assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/async-functions/constructor.js b/js/src/tests/non262/async-functions/constructor.js
new file mode 100644
index 0000000000..ccacb4363a
--- /dev/null
+++ b/js/src/tests/non262/async-functions/constructor.js
@@ -0,0 +1,33 @@
+var BUGNUMBER = 1185106;
+var summary = "async function constructor and prototype";
+
+print(BUGNUMBER + ": " + summary);
+
+var f1 = async function() {};
+
+var AsyncFunction = f1.constructor;
+var AsyncFunctionPrototype = AsyncFunction.prototype;
+
+assertEq(AsyncFunction.name, "AsyncFunction");
+assertEq(AsyncFunction.length, 1);
+assertEq(Object.getPrototypeOf(async function() {}), AsyncFunctionPrototype);
+
+assertEq(AsyncFunctionPrototype.constructor, AsyncFunction);
+
+var f2 = AsyncFunction("await 1");
+assertEq(f2.constructor, AsyncFunction);
+assertEq(f2.length, 0);
+assertEq(Object.getPrototypeOf(f2), AsyncFunctionPrototype);
+
+var f3 = new AsyncFunction("await 1");
+assertEq(f3.constructor, AsyncFunction);
+assertEq(f3.length, 0);
+assertEq(Object.getPrototypeOf(f3), AsyncFunctionPrototype);
+
+var f4 = AsyncFunction("a", "b", "c", "await 1");
+assertEq(f4.constructor, AsyncFunction);
+assertEq(f4.length, 3);
+assertEq(Object.getPrototypeOf(f4), AsyncFunctionPrototype);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/cover-init-name-syntax.js b/js/src/tests/non262/async-functions/cover-init-name-syntax.js
new file mode 100644
index 0000000000..cb7858a67a
--- /dev/null
+++ b/js/src/tests/non262/async-functions/cover-init-name-syntax.js
@@ -0,0 +1,65 @@
+/* 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://mozilla.org/MPL/2.0/. */
+
+// CoverInitName in async arrow parameters.
+async ({a = 1}) => {};
+async ({a = 1}, {b = 2}) => {};
+async ({a = 1}, {b = 2}, {c = 3}) => {};
+async ({a = 1} = {}, {b = 2}, {c = 3}) => {};
+async ({a = 1} = {}, {b = 2} = {}, {c = 3}) => {};
+async ({a = 1} = {}, {b = 2} = {}, {c = 3} = {}) => {};
+
+// CoverInitName nested in array destructuring.
+async ([{a = 0}]) => {};
+
+// CoverInitName nested in rest pattern.
+async ([...[{a = 0}]]) => {};
+
+// CoverInitName nested in object destructuring.
+async ({p: {a = 0}}) => {};
+
+// CoverInitName in CoverCallExpressionAndAsyncArrowHead, but not AsyncArrowHead.
+assertThrowsInstanceOf(() => eval(`
+ NotAsync({a = 1});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ NotAsync({a = 1}, {b = 2}, {c = 3});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ NotAsync({a = 1}, {b = 2}, {c = 3} = {});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ NotAsync({a = 1}, {b = 2} = {}, {c = 3} = {});
+`), SyntaxError);
+
+// Starts with "async", but not called from AssignmentExpression.
+assertThrowsInstanceOf(() => eval(`
+ typeof async({a = 1});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ typeof async({a = 1}, {b = 2}, {c = 3});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ typeof async({a = 1}, {b = 2}, {c = 3} = {});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ typeof async({a = 1}, {b = 2} = {}, {c = 3} = {});
+`), SyntaxError);
+
+// CoverInitName in CoverCallExpressionAndAsyncArrowHead, but not AsyncArrowHead.
+assertThrowsInstanceOf(() => eval(`
+ obj.async({a = 1});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ obj.async({a = 1}, {b = 2}, {c = 3});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ obj.async({a = 1}, {b = 2}, {c = 3} = {});
+`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`
+ obj.async({a = 1}, {b = 2} = {}, {c = 3} = {});
+`), SyntaxError);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/async-functions/create-function-parse-before-getprototype.js b/js/src/tests/non262/async-functions/create-function-parse-before-getprototype.js
new file mode 100644
index 0000000000..413236ec16
--- /dev/null
+++ b/js/src/tests/non262/async-functions/create-function-parse-before-getprototype.js
@@ -0,0 +1,19 @@
+var getProtoCalled = false;
+
+var newTarget = Object.defineProperty(function(){}.bind(), "prototype", {
+ get() {
+ getProtoCalled = true;
+ return null;
+ }
+});
+
+var AsyncFunction = async function(){}.constructor;
+
+assertThrowsInstanceOf(() => {
+ Reflect.construct(AsyncFunction, ["@error"], newTarget);
+}, SyntaxError);
+
+assertEq(getProtoCalled, false);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/duplicate-__proto__.js b/js/src/tests/non262/async-functions/duplicate-__proto__.js
new file mode 100644
index 0000000000..d60b052484
--- /dev/null
+++ b/js/src/tests/non262/async-functions/duplicate-__proto__.js
@@ -0,0 +1,22 @@
+/* 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://mozilla.org/MPL/2.0/. */
+
+// Async arrow function parameters.
+async ({__proto__: a, __proto__: b}) => {};
+
+// Async arrow function parameters with defaults (initially parsed as destructuring assignment).
+async ({__proto__: a, __proto__: b} = {}) => {};
+
+// Duplicate __proto__ in CoverCallExpressionAndAsyncArrowHead, but not AsyncArrowHead.
+assertThrowsInstanceOf(() => eval(`
+ NotAsync({__proto__: a, __proto__: b});
+`), SyntaxError);
+
+// Starts with "async", but not called from AssignmentExpression.
+assertThrowsInstanceOf(() => eval(`
+ typeof async({__proto__: a, __proto__: b});
+`), SyntaxError);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/async-functions/forbidden-as-consequent.js b/js/src/tests/non262/async-functions/forbidden-as-consequent.js
new file mode 100644
index 0000000000..656ed46deb
--- /dev/null
+++ b/js/src/tests/non262/async-functions/forbidden-as-consequent.js
@@ -0,0 +1,14 @@
+/* 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://mozilla.org/MPL/2.0/. */
+
+assertThrowsInstanceOf(() => eval("if (1) async function foo() {}"),
+ SyntaxError);
+assertThrowsInstanceOf(() => eval("'use strict'; if (1) async function foo() {}"),
+ SyntaxError);
+
+var async = 42;
+assertEq(eval("if (1) async \n function foo() {}"), 42);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/identity.js b/js/src/tests/non262/async-functions/identity.js
new file mode 100644
index 0000000000..f3876bf233
--- /dev/null
+++ b/js/src/tests/non262/async-functions/identity.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1185106;
+var summary = "Named async function expression should get wrapped function for the name inside it";
+
+print(BUGNUMBER + ": " + summary);
+
+var expr = async function foo() {
+ return foo;
+};
+assertEventuallyEq(expr(), expr);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/inner-caller.js b/js/src/tests/non262/async-functions/inner-caller.js
new file mode 100644
index 0000000000..f76f978f01
--- /dev/null
+++ b/js/src/tests/non262/async-functions/inner-caller.js
@@ -0,0 +1,17 @@
+function g() {
+ return g.caller;
+}
+
+(async function f() {
+ var inner = g();
+ assertEq(inner, null);
+})();
+
+(async function f() {
+ "use strict";
+ var inner = g();
+ assertEq(inner, null);
+})();
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/length.js b/js/src/tests/non262/async-functions/length.js
new file mode 100644
index 0000000000..da95e23b89
--- /dev/null
+++ b/js/src/tests/non262/async-functions/length.js
@@ -0,0 +1,12 @@
+var BUGNUMBER = 1185106;
+var summary = "async function length";
+
+print(BUGNUMBER + ": " + summary);
+
+assertEq(async function() {}.length, 0);
+assertEq(async function(a) {}.length, 1);
+assertEq(async function(a, b, c) {}.length, 3);
+assertEq(async function(a, b, c, ...d) {}.length, 3);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/methods.js b/js/src/tests/non262/async-functions/methods.js
new file mode 100644
index 0000000000..061a0e8267
--- /dev/null
+++ b/js/src/tests/non262/async-functions/methods.js
@@ -0,0 +1,61 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+var BUGNUMBER = 1185106;
+var summary = "async methods semantics";
+
+print(BUGNUMBER + ": " + summary);
+
+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;
+ }
+ async 10() {
+ return 46;
+ }
+ async ["foo"]() {
+ return 47;
+ }
+}
+
+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();
+
+assertEventuallyEq(x.getValue(), 42);
+assertEventuallyEq(x.increment(), 43);
+assertEventuallyEq(x[10](), 46);
+assertEventuallyEq(x.foo(), 47);
+assertEventuallyEq(X.getStaticValue(), 44);
+assertEventuallyEq(objLiteral.get(), 45);
+assertEventuallyEq(y.getBaseClassName(), 'X');
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/no-expression-closure.js b/js/src/tests/non262/async-functions/no-expression-closure.js
new file mode 100644
index 0000000000..44d139fe41
--- /dev/null
+++ b/js/src/tests/non262/async-functions/no-expression-closure.js
@@ -0,0 +1,17 @@
+function assertSyntaxError(code) {
+ assertThrowsInstanceOf(function () { Function(code); }, SyntaxError, "Function:" + code);
+ assertThrowsInstanceOf(function () { eval(code); }, SyntaxError, "eval:" + code);
+ var ieval = eval;
+ assertThrowsInstanceOf(function () { ieval(code); }, SyntaxError, "indirect eval:" + code);
+}
+
+// AsyncFunction statement
+assertSyntaxError(`async function f() 0`);
+
+// AsyncFunction expression
+assertSyntaxError(`void async function() 0`);
+assertSyntaxError(`void async function f() 0`);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/parameters-error-reject-promise.js b/js/src/tests/non262/async-functions/parameters-error-reject-promise.js
new file mode 100644
index 0000000000..a6cca7cdde
--- /dev/null
+++ b/js/src/tests/non262/async-functions/parameters-error-reject-promise.js
@@ -0,0 +1,56 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+class ExpectedError extends Error {
+ name = "ExpectedError";
+}
+
+class UnexpectedError extends Error {
+ name = "UnexpectedError";
+}
+
+function throwExpectedError() {
+ throw new ExpectedError();
+}
+
+async function throwsInParameterExpression(a = throwExpectedError()) {
+ throw new UnexpectedError();
+}
+assertEventuallyThrows(throwsInParameterExpression(), ExpectedError);
+
+async function throwsInObjectDestructuringParameterEmpty({}) {
+ throw new UnexpectedError();
+}
+assertEventuallyThrows(throwsInObjectDestructuringParameterEmpty(), TypeError);
+
+let objectThrowingExpectedError = {
+ get a() {
+ throw new ExpectedError();
+ }
+}
+
+async function throwsInObjectDestructuringParameter({a}) {
+ throw new UnexpectedError();
+}
+assertEventuallyThrows(throwsInObjectDestructuringParameter(), TypeError);
+assertEventuallyThrows(throwsInObjectDestructuringParameter(objectThrowingExpectedError), ExpectedError);
+
+let iteratorThrowingExpectedError = {
+ [Symbol.iterator]() {
+ throw new ExpectedError();
+ }
+};
+
+async function throwsInArrayDestructuringParameterEmpty([]) {
+ throw new UnexpectedError();
+}
+assertEventuallyThrows(throwsInArrayDestructuringParameterEmpty(), TypeError);
+assertEventuallyThrows(throwsInArrayDestructuringParameterEmpty(iteratorThrowingExpectedError), ExpectedError);
+
+async function throwsInArrayDestructuringParameter([a]) {
+ throw new UnexpectedError();
+}
+assertEventuallyThrows(throwsInArrayDestructuringParameter(), TypeError);
+assertEventuallyThrows(throwsInArrayDestructuringParameter(iteratorThrowingExpectedError), ExpectedError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/properties.js b/js/src/tests/non262/async-functions/properties.js
new file mode 100644
index 0000000000..ca383901bb
--- /dev/null
+++ b/js/src/tests/non262/async-functions/properties.js
@@ -0,0 +1,76 @@
+/* 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://mozilla.org/MPL/2.0/. */
+
+function assertOwnDescriptor(object, propertyKey, expected) {
+ var desc = Object.getOwnPropertyDescriptor(object, propertyKey);
+ if (desc === undefined) {
+ assertEq(expected, undefined, "Property shouldn't be present");
+ return;
+ }
+
+ assertEq(desc.enumerable, expected.enumerable, `${String(propertyKey)}.[[Enumerable]]`);
+ assertEq(desc.configurable, expected.configurable, `${String(propertyKey)}.[[Configurable]]`);
+
+ if (Object.prototype.hasOwnProperty.call(desc, "value")) {
+ assertEq(desc.value, expected.value, `${String(propertyKey)}.[[Value]]`);
+ assertEq(desc.writable, expected.writable, `${String(propertyKey)}.[[Writable]]`);
+ } else {
+ assertEq(desc.get, expected.get, `${String(propertyKey)}.[[Get]]`);
+ assertEq(desc.set, expected.set, `${String(propertyKey)}.[[Set]]`);
+ }
+}
+
+async function asyncFunc(){}
+var AsyncFunctionPrototype = Object.getPrototypeOf(asyncFunc);
+var AsyncFunction = AsyncFunctionPrototype.constructor;
+
+
+// ES2017, 25.5.2 Properties of the AsyncFunction Constructor
+
+assertEqArray(Object.getOwnPropertyNames(AsyncFunction).sort(), ["length", "name", "prototype"]);
+assertEqArray(Object.getOwnPropertySymbols(AsyncFunction), []);
+
+assertOwnDescriptor(AsyncFunction, "length", {
+ value: 1, writable: false, enumerable: false, configurable: true
+});
+
+assertOwnDescriptor(AsyncFunction, "name", {
+ value: "AsyncFunction", writable: false, enumerable: false, configurable: true
+});
+
+assertOwnDescriptor(AsyncFunction, "prototype", {
+ value: AsyncFunctionPrototype, writable: false, enumerable: false, configurable: false
+});
+
+
+// ES2017, 25.5.3 Properties of the AsyncFunction Prototype Object
+
+assertEqArray(Object.getOwnPropertyNames(AsyncFunctionPrototype).sort(), ["constructor"]);
+assertEqArray(Object.getOwnPropertySymbols(AsyncFunctionPrototype), [Symbol.toStringTag]);
+
+assertOwnDescriptor(AsyncFunctionPrototype, "constructor", {
+ value: AsyncFunction, writable: false, enumerable: false, configurable: true
+});
+
+assertOwnDescriptor(AsyncFunctionPrototype, Symbol.toStringTag, {
+ value: "AsyncFunction", writable: false, enumerable: false, configurable: true
+});
+
+
+// ES2017, 25.5.4 AsyncFunction Instances
+
+assertEqArray(Object.getOwnPropertyNames(asyncFunc).sort(), ["length", "name"]);
+assertEqArray(Object.getOwnPropertySymbols(asyncFunc), []);
+
+assertOwnDescriptor(asyncFunc, "length", {
+ value: 0, writable: false, enumerable: false, configurable: true
+});
+
+assertOwnDescriptor(asyncFunc, "name", {
+ value: "asyncFunc", writable: false, enumerable: false, configurable: true
+});
+
+
+if (typeof reportCompare == "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/property.js b/js/src/tests/non262/async-functions/property.js
new file mode 100644
index 0000000000..53f779c330
--- /dev/null
+++ b/js/src/tests/non262/async-functions/property.js
@@ -0,0 +1,49 @@
+var BUGNUMBER = 1185106;
+var summary = "async name token in property and object destructuring pattern";
+
+print(BUGNUMBER + ": " + summary);
+
+{
+ let a = { async: 10 };
+ assertEq(a.async, 10);
+}
+
+{
+ let a = { async() {} };
+ assertEq(a.async instanceof Function, true);
+ assertEq(a.async.name, "async");
+}
+
+{
+ let async = 11;
+ let a = { async };
+ assertEq(a.async, 11);
+}
+
+{
+ let { async } = { async: 12 };
+ assertEq(async, 12);
+}
+
+{
+ let { async = 13 } = {};
+ assertEq(async, 13);
+}
+
+{
+ let { async: a = 14 } = {};
+ assertEq(a, 14);
+}
+
+{
+ let { async, other } = { async: 15, other: 16 };
+ assertEq(async, 15);
+ assertEq(other, 16);
+
+ let a = { async, other };
+ assertEq(a.async, 15);
+ assertEq(a.other, 16);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/semantics.js b/js/src/tests/non262/async-functions/semantics.js
new file mode 100644
index 0000000000..5814890a63
--- /dev/null
+++ b/js/src/tests/non262/async-functions/semantics.js
@@ -0,0 +1,169 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+var BUGNUMBER = 1185106;
+var summary = "async functions semantics";
+
+print(BUGNUMBER + ": " + summary);
+
+async function empty() {
+}
+assertEventuallyEq(empty(), undefined);
+
+async function simpleReturn() {
+ return 1;
+}
+assertEventuallyEq(simpleReturn(), 1);
+
+async function simpleAwait() {
+ var result = await 2;
+ return result;
+}
+assertEventuallyEq(simpleAwait(), 2);
+
+async function simpleAwaitAsync() {
+ var result = await simpleReturn();
+ return 2 + result;
+}
+assertEventuallyEq(simpleAwaitAsync(), 3);
+
+async function returnOtherAsync() {
+ return 1 + await simpleAwaitAsync();
+}
+assertEventuallyEq(returnOtherAsync(), 4);
+
+async function simpleThrower() {
+ throw new Error();
+}
+assertEventuallyThrows(simpleThrower(), Error);
+
+async function delegatedThrower() {
+ var val = await simpleThrower();
+ return val;
+}
+
+async function tryCatch() {
+ try {
+ await delegatedThrower();
+ return 'FAILED';
+ } catch (_) {
+ return 5;
+ }
+}
+assertEventuallyEq(tryCatch(), 5);
+
+async function tryCatchThrow() {
+ try {
+ await delegatedThrower();
+ return 'FAILED';
+ } catch (_) {
+ return delegatedThrower();
+ }
+}
+assertEventuallyThrows(tryCatchThrow(), Error);
+
+async function wellFinally() {
+ try {
+ await delegatedThrower();
+ } catch (_) {
+ return 'FAILED';
+ } finally {
+ return 6;
+ }
+}
+assertEventuallyEq(wellFinally(), 6);
+
+async function finallyMayFail() {
+ try {
+ await delegatedThrower();
+ } catch (_) {
+ return 5;
+ } finally {
+ return delegatedThrower();
+ }
+}
+assertEventuallyThrows(finallyMayFail(), Error);
+
+async function embedded() {
+ async function inner() {
+ return 7;
+ }
+ return await inner();
+}
+assertEventuallyEq(embedded(), 7);
+
+// recursion, it works!
+async function fib(n) {
+ return (n == 0 || n == 1) ? n : await fib(n - 1) + await fib(n - 2);
+}
+assertEventuallyEq(fib(6), 8);
+
+// mutual recursion
+async function isOdd(n) {
+ async function isEven(n) {
+ return n === 0 || await isOdd(n - 1);
+ }
+ return n !== 0 && await isEven(n - 1);
+}
+assertEventuallyEq(isOdd(12).then(v => v ? "oops" : 12), 12);
+
+// recursion, take three!
+var hardcoreFib = async function fib2(n) {
+ return (n == 0 || n == 1) ? n : await fib2(n - 1) + await fib2(n - 2);
+}
+assertEventuallyEq(hardcoreFib(7), 13);
+
+var asyncExpr = async function() {
+ return 10;
+}
+assertEventuallyEq(asyncExpr(), 10);
+
+var namedAsyncExpr = async function simple() {
+ return 11;
+}
+assertEventuallyEq(namedAsyncExpr(), 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;
+}
+assertEventuallyEq(executionOrder(), 9);
+
+async function miscellaneous() {
+ if (arguments.length === 3 &&
+ arguments.callee.name === "miscellaneous")
+ return 14;
+}
+assertEventuallyEq(miscellaneous(1, 2, 3), 14);
+
+function thrower() {
+ throw 15;
+}
+
+async function defaultArgs(arg = thrower()) {
+}
+assertEventuallyEq(defaultArgs().catch(e => e), 15);
+
+let arrowAwaitExpr = async () => await 2;
+assertEventuallyEq(arrowAwaitExpr(), 2);
+
+let arrowAwaitBlock = async () => { return await 2; };
+assertEventuallyEq(arrowAwaitBlock(), 2);
+
+// Async functions are not constructible
+assertThrowsInstanceOf(() => {
+ async function Person() {
+
+ }
+ new Person();
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/shell.js b/js/src/tests/non262/async-functions/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/async-functions/shell.js
diff --git a/js/src/tests/non262/async-functions/subclass.js b/js/src/tests/non262/async-functions/subclass.js
new file mode 100644
index 0000000000..da20ab19b8
--- /dev/null
+++ b/js/src/tests/non262/async-functions/subclass.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+/* 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://mozilla.org/MPL/2.0/. */
+
+const AsyncFunction = async function(){}.constructor;
+
+class MyAsync extends AsyncFunction {}
+
+// MyGen inherits from %AsyncFunction%.
+assertEq(Object.getPrototypeOf(MyAsync), AsyncFunction);
+
+// MyGen.prototype inherits from %AsyncFunctionPrototype%.
+assertEq(Object.getPrototypeOf(MyAsync.prototype), AsyncFunction.prototype);
+
+var fn = new MyAsync("return await 'ok';");
+
+// fn inherits from MyAsync.prototype.
+assertEq(Object.getPrototypeOf(fn), MyAsync.prototype);
+
+// Ensure the new async function can be executed.
+var promise = fn();
+
+// promise inherits from %Promise.prototype%.
+assertEq(Object.getPrototypeOf(promise), Promise.prototype);
+
+// Computes the expected result.
+assertEventuallyEq(promise, "ok");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/async-functions/syntax-arrow.js b/js/src/tests/non262/async-functions/syntax-arrow.js
new file mode 100644
index 0000000000..a2c96e7dd9
--- /dev/null
+++ b/js/src/tests/non262/async-functions/syntax-arrow.js
@@ -0,0 +1,104 @@
+var BUGNUMBER = 1185106;
+var summary = "async arrow function syntax";
+
+print(BUGNUMBER + ": " + summary);
+
+if (typeof Reflect !== "undefined" && Reflect.parse) {
+ // Parameters.
+ Reflect.parse("async () => 1");
+ Reflect.parse("async a => 1");
+ Reflect.parse("async (a) => 1");
+ Reflect.parse("async async => 1");
+ Reflect.parse("async (async) => 1");
+ Reflect.parse("async ([a]) => 1");
+ Reflect.parse("async ([a, b]) => 1");
+ Reflect.parse("async ({a}) => 1");
+ Reflect.parse("async ({a, b}) => 1");
+
+ assertThrowsInstanceOf(() => Reflect.parse("async await => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async (await) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ([await]) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ({await}) => 1"), SyntaxError);
+
+ assertThrowsInstanceOf(() => Reflect.parse("async (a=await) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ([a=await]) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ({a=await}) => 1"), SyntaxError);
+
+ assertThrowsInstanceOf(() => Reflect.parse("async (a=await 1) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ([a=await 1]) => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async ({a=await 1}) => 1"), SyntaxError);
+
+ assertThrowsInstanceOf(() => Reflect.parse("async [a] => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async [a, b] => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async {a} => 1"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async {a: b} => 1"), SyntaxError);
+
+ // Expression body.
+ Reflect.parse("async a => a == b");
+
+ // Expression body with nested async function.
+ Reflect.parse("async a => async");
+ Reflect.parse("async a => async b => c");
+ Reflect.parse("async a => async function() {}");
+ Reflect.parse("async a => async function b() {}");
+
+ assertThrowsInstanceOf(() => Reflect.parse("async a => async b"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async a => async function"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async a => async function()"), SyntaxError);
+
+ // Expression body with `await`.
+ Reflect.parse("async a => await 1");
+ Reflect.parse("async a => await await 1");
+ Reflect.parse("async a => await await await 1");
+
+ assertThrowsInstanceOf(() => Reflect.parse("async a => await"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async a => await await"), SyntaxError);
+
+ // `await` is Unary Expression and it cannot have `async` function as an
+ // operand.
+ assertThrowsInstanceOf(() => Reflect.parse("async a => await async X => Y"), SyntaxError);
+ Reflect.parse("async a => await (async X => Y)");
+ // But it can have `async` identifier as an operand.
+ Reflect.parse("async async => await async");
+
+ // Block body.
+ Reflect.parse("async X => {yield}");
+
+ // `yield` handling.
+ Reflect.parse("async X => yield");
+ Reflect.parse("async yield => X");
+ Reflect.parse("async yield => yield");
+ Reflect.parse("async X => {yield}");
+
+ Reflect.parse("async X => {yield}");
+ Reflect.parse("async yield => {X}");
+ Reflect.parse("async yield => {yield}");
+ Reflect.parse("function* g() { async X => yield }");
+
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; async yield => X"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; async (yield) => X"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; async X => yield"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; async X => {yield}"), SyntaxError);
+
+ assertThrows(() => Reflect.parse("function* g() { async yield => X }"));
+ assertThrows(() => Reflect.parse("function* g() { async (yield) => X }"));
+ assertThrows(() => Reflect.parse("function* g() { async ([yield]) => X }"));
+ assertThrows(() => Reflect.parse("function* g() { async ({yield}) => X }"));
+
+ // Not async functions.
+ Reflect.parse("async ()");
+ Reflect.parse("async (a)");
+ Reflect.parse("async (async)");
+ Reflect.parse("async ([a])");
+ Reflect.parse("async ([a, b])");
+ Reflect.parse("async ({a})");
+ Reflect.parse("async ({a, b})");
+
+ // Async arrow function is assignment expression.
+ Reflect.parse("a ? async () => {1} : b");
+ Reflect.parse("a ? b : async () => {1}");
+ assertThrowsInstanceOf(() => Reflect.parse("async () => {1} ? a : b"), SyntaxError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/syntax-modules.js b/js/src/tests/non262/async-functions/syntax-modules.js
new file mode 100644
index 0000000000..265ece9264
--- /dev/null
+++ b/js/src/tests/non262/async-functions/syntax-modules.js
@@ -0,0 +1,28 @@
+var BUGNUMBER = 1185106;
+var summary = "async/await syntax in module";
+
+print(BUGNUMBER + ": " + summary);
+
+if (typeof parseModule === "function") {
+ parseModule("async function f() { await 3; }");
+ parseModule("async function f() { await 3; }");
+ assertThrowsInstanceOf(() => parseModule("function f() { await 5; }"), SyntaxError);
+ assertThrowsInstanceOf(() => parseModule("() => { await 5; }"), SyntaxError);
+ assertThrowsInstanceOf(() => parseModule("export var await;"), SyntaxError);
+ assertThrowsInstanceOf(() => parseModule("await => 1;"), SyntaxError);
+ assertThrowsInstanceOf(() => parseModule("async function f() { function g() { await 3; } }"), SyntaxError);
+
+ if (typeof Reflect !== "undefined" && Reflect.parse) {
+ Reflect.parse("export async function f() {}", { target: "module" });
+ assertThrowsInstanceOf(() => Reflect.parse("export async function() {}", { target: "module" }), SyntaxError);
+
+ Reflect.parse("export default async function() {}", { target: "module" });
+ Reflect.parse("export default async function f() {}", { target: "module" });
+
+ assertThrowsInstanceOf(() => Reflect.parse("export default async function() { yield; }", { target: "module" }), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("export default async function() { yield = 1; }", { target: "module" }), SyntaxError);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/syntax.js b/js/src/tests/non262/async-functions/syntax.js
new file mode 100644
index 0000000000..a5ec254e2e
--- /dev/null
+++ b/js/src/tests/non262/async-functions/syntax.js
@@ -0,0 +1,83 @@
+var BUGNUMBER = 1185106;
+var summary = "async/await syntax";
+
+print(BUGNUMBER + ": " + summary);
+
+if (typeof Reflect !== "undefined" && Reflect.parse) {
+ assertEq(Reflect.parse("function a() {}").body[0].async, false);
+ assertEq(Reflect.parse("function* a() {}").body[0].async, false);
+ assertEq(Reflect.parse("async function a() {}").body[0].async, true);
+ assertEq(Reflect.parse("() => {}").body[0].async, undefined);
+
+ // No line terminator after async
+ assertEq(Reflect.parse("async\nfunction a(){}").body[0].expression.name, "async");
+
+ // Async function expressions
+ assertEq(Reflect.parse("(async function() {})()").body[0].expression.callee.async, true);
+ assertEq(Reflect.parse("var k = async function() {}").body[0].declarations[0].init.async, true);
+ assertEq(Reflect.parse("var nmd = async function named() {}").body[0].declarations[0].init.id.name, "named");
+
+ // `await` handling for function declaration name inherits.
+ assertEq(Reflect.parse("async function await() {}").body[0].id.name, "await");
+ assertThrowsInstanceOf(() => Reflect.parse("async function f() { async function await() {} }"), SyntaxError);
+
+ // `await` is not allowed in function expression name.
+ assertThrowsInstanceOf(() => Reflect.parse("(async function await() {})"), SyntaxError);
+
+ // Awaiting not directly inside an async function is not allowed
+ assertThrowsInstanceOf(() => Reflect.parse("await 4;"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("function a() { await 4; }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("function* a() { await 4; }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function k() { function a() { await 4; } }"), SyntaxError);
+
+ // Await is not allowed as a default expr.
+ assertThrowsInstanceOf(() => Reflect.parse("async function a(k = await 3) {}"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b(k = await 3) {} }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b(k = [await 3]) {} }"), SyntaxError);
+
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b([k = await 3]) {} }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b([k = [await 3]]) {} }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b({k = await 3}) {} }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { async function b({k = [await 3]}) {} }"), SyntaxError);
+
+ // Await is not legal as an identifier in an async function.
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { var await = 4; }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("async function a() { return await; }"), SyntaxError);
+
+ // Await is still available as an identifier name in strict mode code.
+ Reflect.parse("function a() { 'use strict'; var await = 3; }");
+ Reflect.parse("'use strict'; var await = 3;");
+
+ // Await is treated differently depending on context. Various cases.
+ Reflect.parse("var await = 3; async function a() { await 4; }");
+ Reflect.parse("async function a() { await 4; } var await = 5");
+ Reflect.parse("async function a() { function b() { return await; } }");
+
+ Reflect.parse("async function a() { var k = { async: 4 } }");
+
+ Reflect.parse("function a() { await: 4 }");
+
+ assertEq(Reflect.parse("async function a() { await 4; }")
+ .body[0].body.body[0].expression.operator, "await");
+
+ assertEq(Reflect.parse("async function a() { async function b() { await 4; } }")
+ .body[0].body.body[0].body.body[0].expression.operator, "await");
+
+ // operator priority test
+ assertEq(Reflect.parse("async function a() { await 2 + 3; }")
+ .body[0].body.body[0].expression.left.argument.value, 2);
+ assertEq(Reflect.parse("async function a() { await 2 + 3; }")
+ .body[0].body.body[0].expression.left.operator, "await");
+ assertEq(Reflect.parse("async function a() { await 2 + 3; }")
+ .body[0].body.body[0].expression.right.value, 3);
+
+ // blocks and other constructions
+ assertEq(Reflect.parse("{ async function a() { return 2; } }")
+ .body[0].body[0].async, true);
+
+ // Async function expression is primary expression.
+ Reflect.parse("(async function a() {}.constructor)");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/toSource.js b/js/src/tests/non262/async-functions/toSource.js
new file mode 100644
index 0000000000..3cd2943aec
--- /dev/null
+++ b/js/src/tests/non262/async-functions/toSource.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!Function.prototype.toSource)
+
+var BUGNUMBER = 1335025;
+var summary = "(non-standard) async function toSource";
+
+print(BUGNUMBER + ": " + summary);
+
+async function f1(a, b, c) { await a; }
+
+assertEq(f1.toSource(),
+ "async function f1(a, b, c) { await a; }");
+
+assertEq(async function (a, b, c) { await a; }.toSource(),
+ "(async function (a, b, c) { await a; })");
+
+assertEq((async (a, b, c) => await a).toSource(),
+ "async (a, b, c) => await a");
+
+assertEq((async (a, b, c) => { await a; }).toSource(),
+ "async (a, b, c) => { await a; }");
+
+assertEq({ async foo(a, b, c) { await a; } }.foo.toSource(),
+ "async foo(a, b, c) { await a; }");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/toString.js b/js/src/tests/non262/async-functions/toString.js
new file mode 100644
index 0000000000..a4ecd7b653
--- /dev/null
+++ b/js/src/tests/non262/async-functions/toString.js
@@ -0,0 +1,24 @@
+var BUGNUMBER = 1185106;
+var summary = "async function toString";
+
+print(BUGNUMBER + ": " + summary);
+
+async function f1(a, b, c) { await a; }
+
+assertEq(f1.toString(),
+ "async function f1(a, b, c) { await a; }");
+
+assertEq(async function (a, b, c) { await a; }.toString(),
+ "async function (a, b, c) { await a; }");
+
+assertEq((async (a, b, c) => await a).toString(),
+ "async (a, b, c) => await a");
+
+assertEq((async (a, b, c) => { await a; }).toString(),
+ "async (a, b, c) => { await a; }");
+
+assertEq({ async foo(a, b, c) { await a; } }.foo.toString(),
+ "async foo(a, b, c) { await a; }");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/async-functions/yield.js b/js/src/tests/non262/async-functions/yield.js
new file mode 100644
index 0000000000..1d5b836a33
--- /dev/null
+++ b/js/src/tests/non262/async-functions/yield.js
@@ -0,0 +1,71 @@
+var BUGNUMBER = 1185106;
+var summary = "yield handling in async function";
+
+print(BUGNUMBER + ": " + summary);
+
+function testPassArgsBody(argsbody) {
+ Reflect.parse(`async function a${argsbody}`);
+ Reflect.parse(`(async function a${argsbody})`);
+ Reflect.parse(`(async function ${argsbody})`);
+ Reflect.parse(`({ async m${argsbody} })`);
+}
+
+function testErrorArgsBody(argsbody, prefix="") {
+ assertThrowsInstanceOf(() => Reflect.parse(`${prefix} async function a${argsbody}`), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse(`${prefix} (async function a${argsbody})`), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse(`${prefix} (async function ${argsbody})`), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse(`${prefix} ({ async m${argsbody} })`), SyntaxError);
+}
+
+function testErrorArgsBodyStrict(argsbody) {
+ testErrorArgsBody(argsbody);
+ testErrorArgsBody(argsbody, "'use strict'; ");
+ assertThrowsInstanceOf(() => Reflect.parse(`class X { async m${argsbody} }`), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse(`class X { static async m${argsbody} }`), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse(`export default async function ${argsbody}`, { target: "module" }), SyntaxError);
+}
+
+if (typeof Reflect !== "undefined" && Reflect.parse) {
+ // `yield` handling is inherited in async function declaration name.
+ Reflect.parse("async function yield() {}");
+ Reflect.parse("function f() { async function yield() {} }");
+ assertThrowsInstanceOf(() => Reflect.parse("function* g() { async function yield() {} }"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; async function yield() {}"), SyntaxError);
+
+ // `yield` is treated as an identifier in an async function expression name.
+ // `yield` is not allowed as an identifier in strict code.
+ Reflect.parse("(async function yield() {});");
+ Reflect.parse("function f() { (async function yield() {}); }");
+ Reflect.parse("function* g() { (async function yield() {}); }");
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; (async function yield() {});"), SyntaxError);
+
+ // `yield` handling is inherited in async method name.
+ Reflect.parse("({ async yield() {} });");
+ Reflect.parse("function f() { ({ async yield() {} }); }");
+ Reflect.parse("function* g() { ({ async yield() {} }); }");
+ Reflect.parse("'use strict'; ({ async yield() {} });");
+ Reflect.parse("class X { async yield() {} }");
+
+ Reflect.parse("({ async [yield]() {} });");
+ Reflect.parse("function f() { ({ async [yield]() {} }); }");
+ Reflect.parse("function* g() { ({ async [yield]() {} }); }");
+ assertThrowsInstanceOf(() => Reflect.parse("'use strict'; ({ async [yield]() {} });"), SyntaxError);
+ assertThrowsInstanceOf(() => Reflect.parse("class X { async [yield]() {} }"), SyntaxError);
+
+ // `yield` is treated as an identifier in an async function parameter
+ // `yield` is not allowed as an identifier in strict code.
+ testPassArgsBody("(yield) {}");
+ testPassArgsBody("(yield = 1) {}");
+ testPassArgsBody("(a = yield) {}");
+ testErrorArgsBodyStrict("(yield 3) {}");
+ testErrorArgsBodyStrict("(a = yield 3) {}");
+
+ // `yield` is treated as an identifier in an async function body
+ // `yield` is not allowed as an identifier in strict code.
+ testPassArgsBody("() { yield; }");
+ testPassArgsBody("() { yield = 1; }");
+ testErrorArgsBodyStrict("() { yield 3; }");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);