summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_7/AsyncFunctions
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_7/AsyncFunctions')
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/BoundNames.js21
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/EarlyErrors.js51
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/arguments_callee.js31
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/await-newline.js15
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/clone.js22
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/constructor.js33
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/identity.js14
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/length.js12
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/methods.js61
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/property.js49
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/semantics.js169
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/shell.js0
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/syntax-arrow.js104
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/syntax-modules.js25
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/syntax.js86
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/toString.js24
-rw-r--r--js/src/tests/ecma_7/AsyncFunctions/yield.js71
17 files changed, 788 insertions, 0 deletions
diff --git a/js/src/tests/ecma_7/AsyncFunctions/BoundNames.js b/js/src/tests/ecma_7/AsyncFunctions/BoundNames.js
new file mode 100644
index 000000000..743f4fdcc
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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, "");
+
+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/ecma_7/AsyncFunctions/EarlyErrors.js b/js/src/tests/ecma_7/AsyncFunctions/EarlyErrors.js
new file mode 100644
index 000000000..cb28d104b
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/EarlyErrors.js
@@ -0,0 +1,51 @@
+var BUGNUMBER = 1185106;
+var summary = "EarlyErrors for async function";
+
+print(BUGNUMBER + ": " + summary);
+
+function assertThrowsSE(code) {
+ assertThrows(() => 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/ecma_7/AsyncFunctions/arguments_callee.js b/js/src/tests/ecma_7/AsyncFunctions/arguments_callee.js
new file mode 100644
index 000000000..2a577e0b9
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/await-newline.js b/js/src/tests/ecma_7/AsyncFunctions/await-newline.js
new file mode 100644
index 000000000..dc42fa481
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/clone.js b/js/src/tests/ecma_7/AsyncFunctions/clone.js
new file mode 100644
index 000000000..2a4d5f8e0
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/clone.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs clone, cloneAndExecuteScript, drainJobQueue
+
+// Async function cannot be cloned.
+assertThrowsInstanceOf(() => clone(async function f() {}), TypeError);
+
+// unwrapped async function can be cloned.
+let g = newGlobal();
+cloneAndExecuteScript(`
+async function f() {
+ var a = await 1;
+ var b = await 2;
+ var c = await 3;
+ return a + b + c;
+}
+var V;
+f().then(v => V = v);
+drainJobQueue();
+`, g);
+assertEq(g.V, 6);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_7/AsyncFunctions/constructor.js b/js/src/tests/ecma_7/AsyncFunctions/constructor.js
new file mode 100644
index 000000000..ccacb4363
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/identity.js b/js/src/tests/ecma_7/AsyncFunctions/identity.js
new file mode 100644
index 000000000..f3876bf23
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/length.js b/js/src/tests/ecma_7/AsyncFunctions/length.js
new file mode 100644
index 000000000..da95e23b8
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/methods.js b/js/src/tests/ecma_7/AsyncFunctions/methods.js
new file mode 100644
index 000000000..061a0e826
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/property.js b/js/src/tests/ecma_7/AsyncFunctions/property.js
new file mode 100644
index 000000000..53f779c33
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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/ecma_7/AsyncFunctions/semantics.js b/js/src/tests/ecma_7/AsyncFunctions/semantics.js
new file mode 100644
index 000000000..cb2a04c3f
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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
+assertThrows(() => {
+ async function Person() {
+
+ }
+ new Person();
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_7/AsyncFunctions/shell.js b/js/src/tests/ecma_7/AsyncFunctions/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/shell.js
diff --git a/js/src/tests/ecma_7/AsyncFunctions/syntax-arrow.js b/js/src/tests/ecma_7/AsyncFunctions/syntax-arrow.js
new file mode 100644
index 000000000..6dc8d8621
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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");
+
+ assertThrows(() => Reflect.parse("async await => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async (await) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ([await]) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ({await}) => 1"), SyntaxError);
+
+ assertThrows(() => Reflect.parse("async (a=await) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ([a=await]) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ({a=await}) => 1"), SyntaxError);
+
+ assertThrows(() => Reflect.parse("async (a=await 1) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ([a=await 1]) => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async ({a=await 1}) => 1"), SyntaxError);
+
+ assertThrows(() => Reflect.parse("async [a] => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async [a, b] => 1"), SyntaxError);
+ assertThrows(() => Reflect.parse("async {a} => 1"), SyntaxError);
+ assertThrows(() => 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() {}");
+
+ assertThrows(() => Reflect.parse("async a => async b"), SyntaxError);
+ assertThrows(() => Reflect.parse("async a => async function"), SyntaxError);
+ assertThrows(() => 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");
+
+ assertThrows(() => Reflect.parse("async a => await"), SyntaxError);
+ assertThrows(() => Reflect.parse("async a => await await"), SyntaxError);
+
+ // `await` is Unary Expression and it cannot have `async` function as an
+ // operand.
+ assertThrows(() => 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 }");
+
+ assertThrows(() => Reflect.parse("'use strict'; async yield => X"), SyntaxError);
+ assertThrows(() => Reflect.parse("'use strict'; async (yield) => X"), SyntaxError);
+ assertThrows(() => Reflect.parse("'use strict'; async X => yield"), SyntaxError);
+ assertThrows(() => 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}");
+ assertThrows(() => Reflect.parse("async () => {1} ? a : b"), SyntaxError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_7/AsyncFunctions/syntax-modules.js b/js/src/tests/ecma_7/AsyncFunctions/syntax-modules.js
new file mode 100644
index 000000000..c83056f54
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/syntax-modules.js
@@ -0,0 +1,25 @@
+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; }");
+ assertThrows(() => parseModule("var await = 5;"), SyntaxError);
+ assertThrows(() => parseModule("await;"), SyntaxError);
+ assertThrows(() => parseModule("await 5;"), SyntaxError);
+ assertThrows(() => parseModule("function f() { await 5; }"), SyntaxError);
+ assertThrows(() => parseModule("() => { await 5; }"), SyntaxError);
+ assertThrows(() => parseModule("export var await;"), SyntaxError);
+ assertThrows(() => parseModule("await => 1;"), SyntaxError);
+ assertThrows(() => parseModule("async function f() { function g() { await 3; } }"), SyntaxError);
+
+ if (typeof Reflect !== "undefined" && Reflect.parse) {
+ assertThrows(() => Reflect.parse("export default async function() { yield; }", { target: "module" }), SyntaxError);
+ assertThrows(() => Reflect.parse("export default async function() { yield = 1; }", { target: "module" }), SyntaxError);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_7/AsyncFunctions/syntax.js b/js/src/tests/ecma_7/AsyncFunctions/syntax.js
new file mode 100644
index 000000000..28e5febc1
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/syntax.js
@@ -0,0 +1,86 @@
+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);
+
+ // Async generators are not allowed (with regards to spec)
+ assertThrows(() => Reflect.parse("async function* a() {}"), SyntaxError);
+
+ // 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");
+ assertThrows(() => Reflect.parse("async function f() { async function await() {} }"), SyntaxError);
+
+ // `await` is not allowed in function expression name.
+ assertThrows(() => Reflect.parse("(async function await() {})"), SyntaxError);
+
+ // Awaiting not directly inside an async function is not allowed
+ assertThrows(() => Reflect.parse("await 4;"), SyntaxError);
+ assertThrows(() => Reflect.parse("function a() { await 4; }"), SyntaxError);
+ assertThrows(() => Reflect.parse("function* a() { await 4; }"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function k() { function a() { await 4; } }"), SyntaxError);
+
+ // Await is not allowed as a default expr.
+ assertThrows(() => Reflect.parse("async function a(k = await 3) {}"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function a() { async function b(k = await 3) {} }"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function a() { async function b(k = [await 3]) {} }"), SyntaxError);
+
+ assertThrows(() => Reflect.parse("async function a() { async function b([k = await 3]) {} }"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function a() { async function b([k = [await 3]]) {} }"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function a() { async function b({k = await 3}) {} }"), SyntaxError);
+ assertThrows(() => Reflect.parse("async function a() { async function b({k = [await 3]}) {} }"), SyntaxError);
+
+ // Await is not legal as an identifier in an async function.
+ assertThrows(() => Reflect.parse("async function a() { var await = 4; }"), SyntaxError);
+ assertThrows(() => 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/ecma_7/AsyncFunctions/toString.js b/js/src/tests/ecma_7/AsyncFunctions/toString.js
new file mode 100644
index 000000000..39ae938c3
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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 function foo(a, b, c) { await a; }");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_7/AsyncFunctions/yield.js b/js/src/tests/ecma_7/AsyncFunctions/yield.js
new file mode 100644
index 000000000..348d11f3d
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/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="") {
+ assertThrows(() => Reflect.parse(`${prefix} async function a${argsbody}`), SyntaxError);
+ assertThrows(() => Reflect.parse(`${prefix} (async function a${argsbody})`), SyntaxError);
+ assertThrows(() => Reflect.parse(`${prefix} (async function ${argsbody})`), SyntaxError);
+ assertThrows(() => Reflect.parse(`${prefix} ({ async m${argsbody} })`), SyntaxError);
+}
+
+function testErrorArgsBodyStrict(argsbody) {
+ testErrorArgsBody(argsbody);
+ testErrorArgsBody(argsbody, "'use strict'; ");
+ assertThrows(() => Reflect.parse(`class X { async m${argsbody} }`), SyntaxError);
+ assertThrows(() => Reflect.parse(`class X { static async m${argsbody} }`), SyntaxError);
+ assertThrows(() => 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() {} }");
+ assertThrows(() => Reflect.parse("function* g() { async function yield() {} }"), SyntaxError);
+ assertThrows(() => 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() {}); }");
+ assertThrows(() => 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]() {} }); }");
+ assertThrows(() => Reflect.parse("'use strict'; ({ async [yield]() {} });"), SyntaxError);
+ assertThrows(() => 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);