mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:52:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			239 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| describe("basic usage", () => {
 | |
|     test.xfail("using in normal for loop", () => {
 | |
|         let isDisposed = false;
 | |
|         let lastI = -1;
 | |
|         for (
 | |
|             using x = {
 | |
|                 i: 0,
 | |
|                 tick() {
 | |
|                     this.i++;
 | |
|                 },
 | |
|                 done() {
 | |
|                     return this.i === 3;
 | |
|                 },
 | |
|                 [Symbol.dispose]() {
 | |
|                     isDisposed = true;
 | |
|                 },
 | |
|             };
 | |
|             !x.done();
 | |
|             x.tick()
 | |
|         ) {
 | |
|             expect(isDisposed).toBeFalse();
 | |
|             expect(x.i).toBeGreaterThan(lastI);
 | |
|             lastI = x.i;
 | |
|         }
 | |
| 
 | |
|         expect(isDisposed).toBeTrue();
 | |
|         expect(lastI).toBe(2);
 | |
|     });
 | |
| 
 | |
|     test.xfail("using in normal for loop with expression body", () => {
 | |
|         let isDisposed = false;
 | |
|         let outerI = 0;
 | |
|         for (
 | |
|             using x = {
 | |
|                 i: 0,
 | |
|                 tick() {
 | |
|                     this.i++;
 | |
|                     outerI++;
 | |
|                 },
 | |
|                 done() {
 | |
|                     return this.i === 3;
 | |
|                 },
 | |
|                 [Symbol.dispose]() {
 | |
|                     isDisposed = true;
 | |
|                 },
 | |
|             };
 | |
|             !x.done();
 | |
|             x.tick()
 | |
|         )
 | |
|             expect(isDisposed).toBeFalse();
 | |
| 
 | |
|         expect(isDisposed).toBeTrue();
 | |
|         expect(outerI).toBe(3);
 | |
|     });
 | |
| 
 | |
|     test.xfail("using in for of loop", () => {
 | |
|         const disposable = [];
 | |
|         const values = [];
 | |
| 
 | |
|         function createDisposable(value) {
 | |
|             return {
 | |
|                 value: value,
 | |
|                 [Symbol.dispose]() {
 | |
|                     expect(this.value).toBe(value);
 | |
|                     disposable.push(value);
 | |
|                 }
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         for (using a of [createDisposable('a'), createDisposable('b'), createDisposable('c')]) {
 | |
|             expect(disposable).toEqual(values);
 | |
|             values.push(a.value);
 | |
|         }
 | |
| 
 | |
|         expect(disposable).toEqual(['a', 'b', 'c']);
 | |
|     });
 | |
| 
 | |
|     test.xfail("using in for of loop with expression body", () => {
 | |
|         let disposableCalls = 0;
 | |
|         let i = 0;
 | |
| 
 | |
|         const obj = {
 | |
|             [Symbol.dispose]() {
 | |
|                 disposableCalls++;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         for (using a of [obj, obj, obj])
 | |
|             expect(disposableCalls).toBe(i++);
 | |
| 
 | |
|         expect(disposableCalls).toBe(3);
 | |
|     });
 | |
| 
 | |
|     test.xfail("can have multiple declaration in normal for loop", () => {
 | |
|         let disposed = 0;
 | |
|         const a = {
 | |
|             [Symbol.dispose]() {
 | |
|                 disposed++;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         expect(disposed).toBe(0);
 | |
|         for (using b = a, c = a; false;)
 | |
|             expect().fail();
 | |
| 
 | |
|         expect(disposed).toBe(2);
 | |
|     });
 | |
| 
 | |
|     test.xfail("can have using in block in for loop", () => {
 | |
|         const disposed = [];
 | |
|         const values = [];
 | |
|         for (let i = 0; i < 3; i++) {
 | |
|             using a = {
 | |
|                 val: i,
 | |
|                 [Symbol.dispose]() {
 | |
|                     expect(i).toBe(this.val);
 | |
|                     disposed.push(i);
 | |
|                 },
 | |
|             };
 | |
|             expect(disposed).toEqual(values);
 | |
|             values.push(i);
 | |
|         }
 | |
|         expect(disposed).toEqual([0, 1, 2]);
 | |
|     });
 | |
| 
 | |
|     test.xfail("can have using in block in for-in loop", () => {
 | |
|         const disposed = [];
 | |
|         const values = [];
 | |
|         for (const i in ['a', 'b', 'c']) {
 | |
|             using a = {
 | |
|                 val: i,
 | |
|                 [Symbol.dispose]() {
 | |
|                     expect(i).toBe(this.val);
 | |
|                     disposed.push(i);
 | |
|                 },
 | |
|             };
 | |
|             expect(disposed).toEqual(values);
 | |
|             values.push(i);
 | |
|         }
 | |
|         expect(disposed).toEqual(["0", "1", "2"]);
 | |
|     });
 | |
| 
 | |
|     test.xfail("dispose is called even if throw in for of loop", () => {
 | |
|         let disposableCalls = 0;
 | |
| 
 | |
|         const obj = {
 | |
|             [Symbol.dispose]() {
 | |
|                 expect()
 | |
|                 disposableCalls++;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         try {
 | |
|             for (using a of [obj])
 | |
|                 throw new ExpectationError("Expected in for-of");
 | |
| 
 | |
|             expect().fail("Should have thrown");
 | |
|         } catch (e) {
 | |
|             expect(e).toBeInstanceOf(ExpectationError);
 | |
|             expect(e.message).toBe("Expected in for-of");
 | |
|             expect(disposableCalls).toBe(1);
 | |
|         }
 | |
| 
 | |
|         expect(disposableCalls).toBe(1);
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("using is still a valid variable in loops", () => {
 | |
|     test("for loops var", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (var using = 1; using < 2; using++) {
 | |
|             enteredLoop = true;
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test("for loops const", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (const using = 1; using < 2; ) {
 | |
|             enteredLoop = true;
 | |
|             break;
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test("for loops let", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (let using = 1; using < 2; using++) {
 | |
|             enteredLoop = true;
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test("using in", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (using in [1]) {
 | |
|             enteredLoop = true;
 | |
|             expect(using).toBe("0");
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test("using of", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (using of [1]) {
 | |
|             enteredLoop = true;
 | |
|             expect(using).toBe(1);
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| 
 | |
|     test.xfail("using using of", () => {
 | |
|         let enteredLoop = false;
 | |
|         for (using using of [null]) {
 | |
|             enteredLoop = true;
 | |
|             expect(using).toBeNull();
 | |
|         }
 | |
|         expect(enteredLoop).toBeTrue();
 | |
|     });
 | |
| });
 | |
| 
 | |
| describe("syntax errors", () => {
 | |
|     test("cannot have using as for loop body", () => {
 | |
|         expect("for (;;) using a = {};").not.toEval();
 | |
|         expect("for (x in []) using a = {};").not.toEval();
 | |
|         expect("for (x of []) using a = {};").not.toEval();
 | |
|     });
 | |
| 
 | |
|     test("must have one declaration without initializer in for loop", () => {
 | |
|         expect("for (using x = {} of []) {}").not.toEval();
 | |
|         expect("for (using x, y of []) {}").not.toEval();
 | |
|     });
 | |
| 
 | |
|     test("cannot have using in for-in loop", () => {
 | |
|         expect("for (using x in []) {}").not.toEval();
 | |
|         expect("for (using of in []) {}").not.toEval();
 | |
|         expect("for (using in of []) {}").not.toEval();
 | |
|     });
 | |
| });
 | 
