mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:52:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			202 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| describe("parsing freestanding async functions", () => {
 | |
|     test("simple", () => {
 | |
|         expect(`async function foo() {}`).toEval();
 | |
|         // Although it does not create an async function it is valid.
 | |
|         expect(`async
 | |
|         function foo() {}`).toEval();
 | |
| 
 | |
|         expect(`async function await() {}`).toEval();
 | |
|         expect(`async function yield() {}`).toEval();
 | |
|     });
 | |
|     test("await expression", () => {
 | |
|         expect(`async function foo() { await bar(); }`).toEval();
 | |
|         expect(`async function foo() { await; }`).not.toEval();
 | |
|         expect(`function foo() { await bar(); }`).not.toEval();
 | |
|         expect(`function foo() { await; }`).toEval();
 | |
| 
 | |
|         expect(`\\u0061sync function foo() { await bar(); }`).not.toEval();
 | |
|         expect(`\\u0061sync function foo() { \\u0061wait bar(); }`).not.toEval();
 | |
|         expect(`async function foo() { \\u0061wait bar(); }`).not.toEval();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("parsing object literal async functions", () => {
 | |
|     test("simple", () => {
 | |
|         expect(`x = { async foo() { } }`).toEval();
 | |
|         expect(`x = { async
 | |
|                 foo() { } }`).not.toEval();
 | |
|     });
 | |
| 
 | |
|     test("property on object called async", () => {
 | |
|         expect(`x = { async() { } }`).toEval();
 | |
|         expect(`x = { async() { await 4; } }`).not.toEval();
 | |
|         expect(`x = { async: 3 }`).toEval();
 | |
|         expect(`x = { async: await 3, }`).not.toEval();
 | |
|     });
 | |
| 
 | |
|     test("await expression", () => {
 | |
|         expect(`x = { foo() { await bar(); } }`).not.toEval();
 | |
|         expect(`x = { foo() { await; } }`).toEval();
 | |
|         expect(`x = { async foo() { await bar(); } }`).toEval();
 | |
|         expect(`x = { async foo() { await; } }`).not.toEval();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("parsing classes with async methods", () => {
 | |
|     test("simple", () => {
 | |
|         expect(`class Foo { async foo() {} }`).toEval();
 | |
|         expect(`class Foo { static async foo() {} }`).toEval();
 | |
|         expect(`class Foo { async foo() { await bar(); } }`).toEval();
 | |
|         expect(`class Foo { async foo() { await; } }`).not.toEval();
 | |
|         expect(`class Foo { async constructor() {} }`).not.toEval();
 | |
|     });
 | |
| });
 | |
| 
 | |
| test("function expression names equal to 'await'", () => {
 | |
|     expect(`async function foo() { (function await() {}); }`).toEval();
 | |
|     expect(`async function foo() { function await() {} }`).not.toEval();
 | |
| });
 | |
| 
 | |
| test("async function cannot use await in default parameters", () => {
 | |
|     expect("async function foo(x = await 3) {}").not.toEval();
 | |
|     expect("async function foo(x = await 3) {}").not.toEval();
 | |
| 
 | |
|     // Even as a reference to some variable it is not allowed
 | |
|     expect(`
 | |
|         var await = 4;
 | |
|         async function foo(x = await) {} 
 | |
|     `).not.toEval();
 | |
| });
 | |
| 
 | |
| describe("async arrow functions", () => {
 | |
|     test("basic syntax", () => {
 | |
|         expect("async () => await 3;").toEval();
 | |
|         expect("async param => await param();").toEval();
 | |
|         expect("async (param) => await param();").toEval();
 | |
|         expect("async (a, b) => await a();").toEval();
 | |
| 
 | |
|         expect("async () => { await 3; }").toEval();
 | |
|         expect("async param => { await param(); }").toEval();
 | |
|         expect("async (param) => { await param(); }").toEval();
 | |
|         expect("async (a, b) => { await a(); }").toEval();
 | |
| 
 | |
|         expect(`async
 | |
|                 () => await 3;`).not.toEval();
 | |
| 
 | |
|         expect("async async => await async()").toEval();
 | |
|         expect("async => async").toEval();
 | |
|         expect("async => await async()").not.toEval();
 | |
| 
 | |
|         expect("async (b = await) => await b;").not.toEval();
 | |
|         expect("async (b = await 3) => await b;").not.toEval();
 | |
| 
 | |
|         // Cannot escape the async keyword and get an async arrow function.
 | |
|         expect("\\u0061sync () => await 3").not.toEval();
 | |
| 
 | |
|         expect("for (async of => {};false;) {}").toEval();
 | |
|         expect("for (async of []) {}").not.toEval();
 | |
| 
 | |
|         expect("for (\\u0061sync of []) {}").toEval();
 | |
|         expect("for (\\u0061sync of => {};false;) {}").not.toEval();
 | |
|         expect("for (\\u0061sync => {};false;) {}").toEval();
 | |
|     });
 | |
| 
 | |
|     test("async within a for-loop", () => {
 | |
|         let called = false;
 | |
|         // Unfortunately we cannot really test the more horrible case above.
 | |
|         for (
 | |
|             const f = async of => {
 | |
|                 return of;
 | |
|             };
 | |
|             ;
 | |
| 
 | |
|         ) {
 | |
|             expect(f(43)).toBeInstanceOf(Promise);
 | |
| 
 | |
|             called = true;
 | |
|             break;
 | |
|         }
 | |
|         expect(called).toBeTrue();
 | |
|     });
 | |
| });
 | |
| 
 | |
| test("basic functionality", () => {
 | |
|     test("simple", () => {
 | |
|         let executionValue = null;
 | |
|         let resultValue = null;
 | |
|         async function foo() {
 | |
|             executionValue = "someValue";
 | |
|             return "otherValue";
 | |
|         }
 | |
|         const returnValue = foo();
 | |
|         expect(returnValue).toBeInstanceOf(Promise);
 | |
|         returnValue.then(result => {
 | |
|             resultValue = result;
 | |
|         });
 | |
|         runQueuedPromiseJobs();
 | |
|         expect(executionValue).toBe("someValue");
 | |
|         expect(resultValue).toBe("otherValue");
 | |
|     });
 | |
| 
 | |
|     test("await", () => {
 | |
|         let resultValue = null;
 | |
|         async function foo() {
 | |
|             return "someValue";
 | |
|         }
 | |
|         async function bar() {
 | |
|             resultValue = await foo();
 | |
|         }
 | |
|         bar();
 | |
|         runQueuedPromiseJobs();
 | |
|         expect(resultValue).toBe("someValue");
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("non async function declaration usage of async still works", () => {
 | |
|     test("async as a function", () => {
 | |
|         function async(value = 4) {
 | |
|             return value;
 | |
|         }
 | |
| 
 | |
|         expect(async(0)).toBe(0);
 | |
| 
 | |
|         // We use eval here since it otherwise cannot find the async function.
 | |
|         const evalResult = eval("async(1)");
 | |
|         expect(evalResult).toBe(1);
 | |
|     });
 | |
| 
 | |
|     test("async as a variable", () => {
 | |
|         let async = 3;
 | |
| 
 | |
|         const evalResult = eval("async >= 2");
 | |
|         expect(evalResult).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test("async with line ending does not create a function", () => {
 | |
|         expect(() => {
 | |
|             // The ignore is needed otherwise prettier puts a ';' after async.
 | |
|             // prettier-ignore
 | |
|             async
 | |
|             function f() {}
 | |
|         }).toThrowWithMessage(ReferenceError, "'async' is not defined");
 | |
| 
 | |
|         expect(`async
 | |
|                 function f() { await 3; }`).not.toEval();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("await cannot be used in class static init blocks", () => {
 | |
|     test("directly", () => {
 | |
|         expect("class A{ static { await; } }").not.toEval();
 | |
|         expect("class A{ static { let await = 3; } }").not.toEval();
 | |
|         expect("class A{ static { call(await); } }").not.toEval();
 | |
|         expect("class A{ static { for(const await = 1; false ;) {} } }").not.toEval();
 | |
|     });
 | |
| 
 | |
|     test("via declaration", () => {
 | |
|         expect("class A{ static { class await {} } }").not.toEval();
 | |
|         expect("class A{ static { function await() {} } }").not.toEval();
 | |
|         expect("class A{ static { function* await() {} } }").not.toEval();
 | |
|         expect("class A{ static { async function* await() {} } }").not.toEval();
 | |
|     });
 | |
| });
 | 
