asyncawait-syntax.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // ES6 Async Await tests -- verifies syntax of async/await
  6. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. var tests = [
  8. {
  9. name: "Async and Await keyword as identifier",
  10. body: function () {
  11. var async = [2, 3, 4];
  12. var await = 3;
  13. var o = { async };
  14. o.async = 0;
  15. assert.areEqual(2, async[0], "async[0] === 2");
  16. assert.areEqual(3, await, "await === 3");
  17. assert.areEqual(0, o.async, "o.async === 0");
  18. var i = 0;
  19. var obj = { async, await, i };
  20. assert.areEqual(2, obj.async[0], "obj.async[0] === 2");
  21. assert.areEqual(3, obj.await, "obj.await === 3");
  22. }
  23. },
  24. {
  25. name: "Await keyword as identifier",
  26. body: function () {
  27. function method() {
  28. var await = 1;
  29. return await;
  30. }
  31. function await() {
  32. return 2;
  33. }
  34. assert.areEqual(1, method(), "method() === 1");
  35. assert.areEqual(2, await(), "await() === 2");
  36. assert.throws(function () { eval("async function method() { var await = 1; }"); }, SyntaxError, "'await' cannot be used as an identifier in an async function.", "The use of a keyword for an identifier is invalid");
  37. assert.throws(function () { eval("async function method(await;) { }"); }, SyntaxError, "'await' cannot be used as an identifier in an async function.", "The use of a keyword for an identifier is invalid");
  38. assert.throws(function () { eval("async function method() { var x = await; }"); }, SyntaxError, "'await' cannot be used as an identifier in an async function.", "Syntax error");
  39. }
  40. },
  41. {
  42. name: "Async keyword as generator",
  43. body: function () {
  44. assert.throws(function () { eval("async function* badFunction() { }"); }, SyntaxError, "'async' keyword is not allowed with a generator in a statement", "Syntax error");
  45. assert.throws(function () { eval("var badVariable = async function*() { }"); }, SyntaxError, "'async' keyword is not allowed with a generator in an expression", "Syntax error");
  46. assert.throws(function () { eval("var o { async *badFunction() { } };"); }, SyntaxError, "'async' keyword is not allowed with a generator in a object literal member", "Expected ';'");
  47. assert.throws(function () { eval("class C { async *badFunction() { } };"); }, SyntaxError, "'async' keyword is not allowed with a generator in a class member", "Syntax error");
  48. }
  49. },
  50. {
  51. name: "Async classes",
  52. body: function () {
  53. assert.throws(function () { eval("class A { async constructor() {} }"); }, SyntaxError, "'async' keyword is not allowed with a constructor", "Syntax error");
  54. assert.throws(function () { eval("class A { async get foo() {} }"); }, SyntaxError, "'async' keyword is not allowed with a getter", "Syntax error");
  55. assert.throws(function () { eval("class A { async set foo() {} }"); }, SyntaxError, "'async' keyword is not allowed with a setter", "Syntax error");
  56. assert.throws(function () { eval("class A { async static staticAsyncMethod() {} }"); }, SyntaxError, "'async' keyword is not allowed before a static keyword in a function declaration", "Expected '('");
  57. assert.throws(function () { eval("class A { static async prototype() {} }"); }, SyntaxError, "static async method cannot be named 'prototype'", "Syntax error");
  58. }
  59. },
  60. {
  61. name: "Await in eval global scope",
  62. body: function () {
  63. assert.throws(function () { eval("var result = await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  64. assert.throws(function () { eval("await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  65. assert.throws(function () { eval("await a;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  66. assert.throws(function () { eval("await a[0];"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  67. assert.throws(function () { eval("await o.p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  68. assert.throws(function () { eval("a[await p];"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ']'");
  69. assert.throws(function () { eval("a + await p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  70. assert.throws(function () { eval("await p + await q;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
  71. assert.throws(function () { eval("foo(await p, await q);"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ')'");
  72. assert.throws(function () { eval("var lambdaParenNoArg = await () => x < y;"); }, SyntaxError, "'await' keyword is not allowed with a non-async lambda expression", "Syntax error");
  73. assert.throws(function () { eval("var lambdaArgs = await async (a, b ,c) => a + b + c;"); }, SyntaxError, "There miss parenthises", "Expected ';'");
  74. assert.throws(function () { eval("var lambdaArgs = await (async (a, b ,c) => a + b + c);"); }, ReferenceError, "The 'await' function doesn't exists in this scope", "'await' is not defined");
  75. }
  76. },
  77. {
  78. name: "Await in a non-async function",
  79. body: function () {
  80. assert.throws(function () { eval("function method() { var x = await call(); }"); }, SyntaxError, "'await' cannot be used in a non-async function.", "Expected ';'");
  81. }
  82. },
  83. {
  84. name: "Await in strict mode",
  85. body: function () {
  86. "strict mode";
  87. assert.doesNotThrow(function () { eval("function f() { var await; }"); }, "Can name var variable 'await' in non-generator body");
  88. assert.doesNotThrow(function () { eval("function f() { let await; }"); }, "Can name let variable 'await' in non-generator body");
  89. assert.doesNotThrow(function () { eval("function f() { const await = 10; }"); }, "Can name const variable 'await' in non-generator body");
  90. assert.doesNotThrow(function () { eval("function f() { function await() { } }"); }, "Can name function 'await' in non-generator body");
  91. assert.doesNotThrow(function () { eval("function f() { function* await() { } }"); }, "Can name generator function 'await' in non-generator body");
  92. assert.doesNotThrow(function () { eval("function f() { var fe = function await() { } }"); }, "Can name function expression 'await' in non-generator body");
  93. assert.doesNotThrow(function () { eval("function f() { class await { } }"); }, "Can name class 'await' in non-generator body");
  94. assert.doesNotThrow(function () { eval("function f() { var o = { await: 10 } }"); }, "Can name object literal property 'await' in non-generator body");
  95. assert.doesNotThrow(function () { eval("function f() { var o = { get await() { } } }"); }, "Can name accessor method 'await' in non-generator body");
  96. assert.doesNotThrow(function () { eval("function f() { var o = { await() { } } }"); }, "Can name concise method 'await' in non-generator body");
  97. assert.doesNotThrow(function () { eval("function f() { var o = { *await() { } } }"); }, "Can name generator concise method 'await' in non-generator body");
  98. assert.doesNotThrow(function () { eval("function f() { var await = 10; var o = { await }; }"); }, "Can name shorthand property 'await' in non-generator body");
  99. assert.doesNotThrow(function () { eval("function f() { class C { await() { } } }"); }, "Can name method 'await' in non-generator body");
  100. assert.doesNotThrow(function () { eval("function f() { class C { *await() { } } }"); }, "Can name generator method 'await' in non-generator body");
  101. }
  102. },
  103. {
  104. name: "Async function is not a constructor",
  105. body: function () {
  106. async function foo() { }
  107. assert.isFalse(foo.hasOwnProperty('prototype'), "An async function does not have a property named 'prototype'.");
  108. assert.throws(function () { eval("new foo();"); }, TypeError, "An async function cannot be instantiated because it is not have a constructor.", "Function is not a constructor");
  109. }
  110. },
  111. {
  112. name: "async lambda parsing",
  113. body: function () {
  114. var a = async => async;
  115. assert.areEqual(42, a(42), "async used as single parameter name for arrow function still works with async feature turned on");
  116. var b = async () => { };
  117. var c = async x => x;
  118. var d = async (a, b) => { };
  119. assert.doesNotThrow(function () { eval("(async function (z) {})[0]"); }, "Should not throw when async function occurs a type conversion");
  120. }
  121. },
  122. {
  123. name: "It is a Syntax Error if FormalParameters Contains AwaitExpression is true",
  124. body: function () {
  125. assert.throws(function () { eval("async function af(a, b = await a) { }"); }, SyntaxError, "await expressions not allowed in non-strict async function", "'await' expression not allowed in this context");
  126. assert.throws(function () { eval("async function af(a, b = await a) { 'use strict'; }"); }, SyntaxError, "await expressions not allowed in self-strict async function", "'await' expression not allowed in this context");
  127. assert.throws(function () { "use strict"; eval("async function af(a, b = await a) { }"); }, SyntaxError, "await expressions not allowed in parent-strict async function", "'await' expression not allowed in this context");
  128. assert.doesNotThrow(function () { eval("function f(a = async function (x) { await x; }) { a(); } f();"); }, "await is allowed within the body of an async function that appears in a default parameter value expression");
  129. assert.throws(function () { eval("async function af(x) { function f(a = await x) { } f(); } af();"); }, SyntaxError, "await expression is not available within non-async function parameter default expression", "Expected ')'");
  130. }
  131. },
  132. {
  133. name: "[no LineTerminator here] after `async` in grammar",
  134. body: function () {
  135. assert.throws(function () { eval("async\nfunction af() { }"); }, ReferenceError, "AsyncFunctionDeclaration", "'async' is not defined");
  136. assert.throws(function () { eval("var af = async\nfunction () { }"); }, SyntaxError, "AsyncFunctionExpression", "Expected identifier");
  137. assert.throws(function () { eval("var o = { async\nam() { } };"); }, SyntaxError, "AsyncMethod in object literal", "Expected ':'");
  138. assert.throws(function () { eval("class C { async\nam() { } };"); }, SyntaxError, "AsyncMethod in class", "Expected '('");
  139. assert.throws(function () { eval("var aaf = async\n(x, y) => { };"); }, SyntaxError, "AsyncArrowFunction", "Syntax error");
  140. }
  141. },
  142. {
  143. name: "'arguments' and 'eval' are not allowed as formal parameter names in strict mode",
  144. body: function () {
  145. assert.doesNotThrow(function () { eval("async function af(arguments) { }"); }, "'arguments' can be the name of a parameter in a non-strict mode async function");
  146. assert.doesNotThrow(function () { eval("async function af(eval) { }"); }, "'eval' can be the name of a parameter in a non-strict mode async function");
  147. assert.throws(function () { eval("async function af(arguments) { 'use strict'; }"); }, SyntaxError, "'arguments' cannot be the name of a parameter in an async function that turns on strict mode", "Invalid usage of 'arguments' in strict mode");
  148. assert.throws(function () { eval("async function af(eval) { 'use strict'; }"); }, SyntaxError, "'eval' cannot be the name of a parameter in an async function that turns on strict mode", "Invalid usage of 'eval' in strict mode");
  149. assert.throws(function () { "use strict"; eval("async function af(arguments) { }"); }, SyntaxError, "'arguments' cannot be the name of a parameter in an async function that is already in strict mode", "Invalid usage of 'arguments' in strict mode");
  150. assert.throws(function () { "use strict"; eval("async function af(eval) { }"); }, SyntaxError, "'eval' cannot be the name of a parameter in an async function that is already in strict mode", "Invalid usage of 'eval' in strict mode");
  151. }
  152. },
  153. {
  154. name: "duplicate formal parameter names are not allowed in strict mode",
  155. body: function () {
  156. assert.doesNotThrow(function () { eval("async function af(x, x) { }"); }, "duplicate parameter names are allowed in a non-strict mode async function");
  157. assert.doesNotThrow(function () { eval("async function af(a, b, a) { }"); }, "duplicate parameter names are allowed in a non-strict mode async function (when there are other names)");
  158. assert.throws(function () { eval("async (x, x) => { }"); }, SyntaxError, "duplicate parameter names are not allowed in a non-strict mode async arrow function due to arrow function static semantics", "Duplicate formal parameter names not allowed in this context");
  159. assert.throws(function () { eval("async (a, b, a) => { }"); }, SyntaxError, "duplicate parameter names are not allowed in a non-strict mode async arrow function due to arrow function static semantics (when there are other names)", "Duplicate formal parameter names not allowed in this context");
  160. assert.throws(function () { eval("async function af(x, x) { 'use strict'; }"); }, SyntaxError, "duplicate parameter names are not allowed in an async function that turns on strict mode", "Duplicate formal parameter names not allowed in strict mode");
  161. assert.throws(function () { eval("async function af(a, b, a) { 'use strict'; }"); }, SyntaxError, "duplicate parameter names are not allowed in an async function that turns on strict mode (when there are other names)", "Duplicate formal parameter names not allowed in strict mode");
  162. assert.throws(function () { "use strict"; eval("async function af(x, x) { }"); }, SyntaxError, "duplicate parameter names are not allowed in an async function that is already in strict mode", "Duplicate formal parameter names not allowed in strict mode");
  163. assert.throws(function () { "use strict"; eval("async function af(a, b, a) { }"); }, SyntaxError, "duplicate parameter names are not allowed in an async function that is already in strict mode (when there are other names)", "Duplicate formal parameter names not allowed in strict mode");
  164. }
  165. },
  166. {
  167. name: "local variables with same names as formal parameters have proper redeclaration semantics",
  168. body: function () {
  169. assert.doesNotThrow(function () { eval("async function af(x) { var x; }"); }, "var with same name as formal is not an error");
  170. assert.throws(function () { eval("async function af(x) { let x; }"); }, SyntaxError, "let with same name as formal is an error", "Let/Const redeclaration");
  171. assert.throws(function () { eval("async function af(x) { const x = 1; }"); }, SyntaxError, "const with same name as formal is an error", "Let/Const redeclaration");
  172. assert.doesNotThrow(function () { eval("async function af(x) { function x() { } }"); }, "local function with same name as formal is not an error");
  173. assert.throws(function () { eval("async function af(x) { class x { } }"); }, SyntaxError, "class with same name as formal is an error", "Let/Const redeclaration");
  174. }
  175. },
  176. {
  177. name: "await is a keyword and disallowed within arrow function parameter syntax",
  178. body: function () {
  179. assert.throws(function () { eval("async function af() { var a = await => { }; }"); }, SyntaxError, "await cannot appear as the formal name of an unparenthesized arrow function parameter list", "Syntax error");
  180. assert.throws(function () { eval("async function af() { var a = (await) => { }; }"); }, SyntaxError, "await cannot appear as a formal name within parenthesized arrow function parameter list (single formal)", "Syntax error");
  181. assert.throws(function () { eval("async function af() { var a = (x, y, await) => { }; }"); }, SyntaxError, "await cannot appear as a formal name within parenthesized arrow function parameter list (middle formal)", "Syntax error");
  182. assert.throws(function () { eval("async function af() { var a = (x, await, y) => { }; }"); }, SyntaxError, "await cannot appear as a formal name within parenthesized arrow function parameter list (last formal)", "Syntax error");
  183. assert.throws(function () { eval("async function af() { var a = (x = await 0) => { }; }"); }, SyntaxError, "await expression is disallowed within arrow function default parameter expression (single formal)", "'await' expression not allowed in this context");
  184. assert.throws(function () { eval("async function af() { var a = (x, y = await 0, z = 0) => { }; }"); }, SyntaxError, "await expression is disallowed within arrow function default parameter expression (middle formal)", "'await' expression not allowed in this context");
  185. assert.throws(function () { eval("async function af() { var a = (x, y, z = await 0) => { }; }"); }, SyntaxError, "await expression is disallowed within arrow function default parameter expression (last formal)", "'await' expression not allowed in this context");
  186. assert.throws(function () { eval("async (a, await) => { }"); }, SyntaxError, "await cannot appear as the formal name of a parathensized async arrow function", "The use of a keyword for an identifier is invalid");
  187. assert.throws(function () { eval("async await => { }"); }, SyntaxError, "await cannot appear as the formal name of a unparathensized async arrow function", "The use of a keyword for an identifier is invalid");
  188. assert.throws(function () { eval("function () { a = async await => { } }"); }, SyntaxError, "await cannot appear as the formal name of a unparathensized async arrow function expression", "Expected identifier");
  189. assert.throws(function () { eval("async (a, b = await 1) => {}"); }, SyntaxError, "await expression cannot appear in the formals of an async arrow function", "Expected ')'");
  190. assert.throws(function () { eval("async () => { await => { }; }"); }, SyntaxError, "await cannot appear as the formal name of an unparathensized arrow function within an async arrow function", "Syntax error");
  191. assert.throws(function () { eval("async () => { (a, await) => { }; }"); }, SyntaxError, "await cannot appear as the formal name of a parathensized arrow function within an async arrow function", "Syntax error");
  192. assert.throws(function () { eval("async () => { (x, y, z = await 0) => { }; }"); }, SyntaxError, "await expression is disallowed within default parameter expression of an arrow function which is inside an async arrow function", "'await' expression not allowed in this context");
  193. assert.throws(function () { eval("async function af() { (b = (c = await => {}) => {}) => {}; }"); }, SyntaxError, "await cannot appear as the formal name of an unparathensized arrow function in a nested case too", "Syntax error");
  194. }
  195. },
  196. ];
  197. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });