async-await.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. describe("parsing freestanding async functions", () => {
  2. test("simple", () => {
  3. expect(`async function foo() {}`).toEval();
  4. // Although it does not create an async function it is valid.
  5. expect(`async
  6. function foo() {}`).toEval();
  7. expect(`async function await() {}`).toEval();
  8. expect(`async function yield() {}`).toEval();
  9. });
  10. test("await expression", () => {
  11. expect(`async function foo() { await bar(); }`).toEval();
  12. expect(`async function foo() { await; }`).not.toEval();
  13. expect(`function foo() { await bar(); }`).not.toEval();
  14. expect(`function foo() { await; }`).toEval();
  15. expect(`\\u0061sync function foo() { await bar(); }`).not.toEval();
  16. expect(`\\u0061sync function foo() { \\u0061wait bar(); }`).not.toEval();
  17. expect(`async function foo() { \\u0061wait bar(); }`).not.toEval();
  18. });
  19. });
  20. describe("parsing object literal async functions", () => {
  21. test("simple", () => {
  22. expect(`x = { async foo() { } }`).toEval();
  23. expect(`x = { async
  24. foo() { } }`).not.toEval();
  25. });
  26. test("property on object called async", () => {
  27. expect(`x = { async() { } }`).toEval();
  28. expect(`x = { async() { await 4; } }`).not.toEval();
  29. expect(`x = { async: 3 }`).toEval();
  30. expect(`x = { async: await 3, }`).not.toEval();
  31. });
  32. test("await expression", () => {
  33. expect(`x = { foo() { await bar(); } }`).not.toEval();
  34. expect(`x = { foo() { await; } }`).toEval();
  35. expect(`x = { async foo() { await bar(); } }`).toEval();
  36. expect(`x = { async foo() { await; } }`).not.toEval();
  37. });
  38. });
  39. describe("parsing classes with async methods", () => {
  40. test("simple", () => {
  41. expect(`class Foo { async foo() {} }`).toEval();
  42. expect(`class Foo { static async foo() {} }`).toEval();
  43. expect(`class Foo { async foo() { await bar(); } }`).toEval();
  44. expect(`class Foo { async foo() { await; } }`).not.toEval();
  45. expect(`class Foo { async constructor() {} }`).not.toEval();
  46. });
  47. });
  48. test("function expression names equal to 'await'", () => {
  49. expect(`async function foo() { (function await() {}); }`).toEval();
  50. expect(`async function foo() { function await() {} }`).not.toEval();
  51. });
  52. test("async function cannot use await in default parameters", () => {
  53. expect("async function foo(x = await 3) {}").not.toEval();
  54. expect("async function foo(x = await 3) {}").not.toEval();
  55. // Even as a reference to some variable it is not allowed
  56. expect(`
  57. var await = 4;
  58. async function foo(x = await) {}
  59. `).not.toEval();
  60. });
  61. describe("async arrow functions", () => {
  62. test("basic syntax", () => {
  63. expect("async () => await 3;").toEval();
  64. expect("async param => await param();").toEval();
  65. expect("async (param) => await param();").toEval();
  66. expect("async (a, b) => await a();").toEval();
  67. expect("async () => { await 3; }").toEval();
  68. expect("async param => { await param(); }").toEval();
  69. expect("async (param) => { await param(); }").toEval();
  70. expect("async (a, b) => { await a(); }").toEval();
  71. expect(`async
  72. () => await 3;`).not.toEval();
  73. expect("async async => await async()").toEval();
  74. expect("async => async").toEval();
  75. expect("async => await async()").not.toEval();
  76. expect("async (b = await) => await b;").not.toEval();
  77. expect("async (b = await 3) => await b;").not.toEval();
  78. // Cannot escape the async keyword and get an async arrow function.
  79. expect("\\u0061sync () => await 3").not.toEval();
  80. expect("for (async of => {};false;) {}").toEval();
  81. expect("for (async of []) {}").not.toEval();
  82. expect("for (\\u0061sync of []) {}").toEval();
  83. expect("for (\\u0061sync of => {};false;) {}").not.toEval();
  84. expect("for (\\u0061sync => {};false;) {}").toEval();
  85. });
  86. test("async within a for-loop", () => {
  87. let called = false;
  88. // Unfortunately we cannot really test the more horrible case above.
  89. for (
  90. const f = async of => {
  91. return of;
  92. };
  93. ;
  94. ) {
  95. expect(f(43)).toBeInstanceOf(Promise);
  96. called = true;
  97. break;
  98. }
  99. expect(called).toBeTrue();
  100. });
  101. });
  102. test("basic functionality", () => {
  103. test("simple", () => {
  104. let executionValue = null;
  105. let resultValue = null;
  106. async function foo() {
  107. executionValue = "someValue";
  108. return "otherValue";
  109. }
  110. const returnValue = foo();
  111. expect(returnValue).toBeInstanceOf(Promise);
  112. returnValue.then(result => {
  113. resultValue = result;
  114. });
  115. runQueuedPromiseJobs();
  116. expect(executionValue).toBe("someValue");
  117. expect(resultValue).toBe("otherValue");
  118. });
  119. test("await", () => {
  120. let resultValue = null;
  121. async function foo() {
  122. return "someValue";
  123. }
  124. async function bar() {
  125. resultValue = await foo();
  126. }
  127. bar();
  128. runQueuedPromiseJobs();
  129. expect(resultValue).toBe("someValue");
  130. });
  131. });
  132. describe("non async function declaration usage of async still works", () => {
  133. test("async as a function", () => {
  134. function async(value = 4) {
  135. return value;
  136. }
  137. expect(async(0)).toBe(0);
  138. // We use eval here since it otherwise cannot find the async function.
  139. const evalResult = eval("async(1)");
  140. expect(evalResult).toBe(1);
  141. });
  142. test("async as a variable", () => {
  143. let async = 3;
  144. const evalResult = eval("async >= 2");
  145. expect(evalResult).toBeTrue();
  146. });
  147. test("async with line ending does not create a function", () => {
  148. expect(() => {
  149. // The ignore is needed otherwise prettier puts a ';' after async.
  150. // prettier-ignore
  151. async
  152. function f() {}
  153. }).toThrowWithMessage(ReferenceError, "'async' is not defined");
  154. expect(`async
  155. function f() { await 3; }`).not.toEval();
  156. });
  157. });
  158. describe("await cannot be used in class static init blocks", () => {
  159. test("directly", () => {
  160. expect("class A{ static { await; } }").not.toEval();
  161. expect("class A{ static { let await = 3; } }").not.toEval();
  162. expect("class A{ static { call(await); } }").not.toEval();
  163. expect("class A{ static { for(const await = 1; false ;) {} } }").not.toEval();
  164. });
  165. test("via declaration", () => {
  166. expect("class A{ static { class await {} } }").not.toEval();
  167. expect("class A{ static { function await() {} } }").not.toEval();
  168. expect("class A{ static { function* await() {} } }").not.toEval();
  169. expect("class A{ static { async function* await() {} } }").not.toEval();
  170. });
  171. });
  172. describe("await thenables", () => {
  173. test("async returning a thanable variable without fulfilling", () => {
  174. let isCalled = false;
  175. const obj = {
  176. then() {
  177. isCalled = true;
  178. },
  179. };
  180. const f = async () => await obj;
  181. f();
  182. runQueuedPromiseJobs();
  183. expect(isCalled).toBe(true);
  184. });
  185. test("async returning a thanable variable that fulfills", () => {
  186. let isCalled = false;
  187. const obj = {
  188. then(fulfill) {
  189. isCalled = true;
  190. fulfill(isCalled);
  191. },
  192. };
  193. const f = async () => await obj;
  194. f();
  195. runQueuedPromiseJobs();
  196. expect(isCalled).toBe(true);
  197. });
  198. test("async returning a thenable directly without fulfilling", () => {
  199. let isCalled = false;
  200. const f = async () => ({
  201. then() {
  202. isCalled = true;
  203. },
  204. });
  205. f();
  206. runQueuedPromiseJobs();
  207. expect(isCalled).toBe(true);
  208. });
  209. test("async returning a thenable directly that fulfills", () => {
  210. let isCalled = false;
  211. const f = async () => ({
  212. then(fulfill) {
  213. isCalled = true;
  214. fulfill(isCalled);
  215. },
  216. });
  217. f();
  218. runQueuedPromiseJobs();
  219. expect(isCalled).toBe(true);
  220. });
  221. });
  222. describe("await observably looks up constructor of Promise objects", () => {
  223. let calls = 0;
  224. function makeConstructorObservable(promise) {
  225. Object.defineProperty(promise, "constructor", {
  226. get() {
  227. calls++;
  228. return Promise;
  229. },
  230. });
  231. return promise;
  232. }
  233. async function test() {
  234. await makeConstructorObservable(Promise.resolve(1));
  235. await makeConstructorObservable(
  236. new Promise(resolve => {
  237. resolve();
  238. })
  239. );
  240. await makeConstructorObservable(new Boolean(true));
  241. await makeConstructorObservable({});
  242. await makeConstructorObservable(new Number(2));
  243. try {
  244. await makeConstructorObservable(Promise.reject(3));
  245. } catch {}
  246. try {
  247. return makeConstructorObservable(Promise.reject(1));
  248. } catch {
  249. return 2;
  250. }
  251. }
  252. test();
  253. runQueuedPromiseJobs();
  254. expect(calls).toBe(4);
  255. });