mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:32:45 +00:00 
			
		
		
		
	 75dac35d0e
			
		
	
	
		75dac35d0e
		
	
	
	
	
		
			
			This fixes two issues with running a TryStatement finalizer: - Temporarily store and clear the exception, if any, so we can run the finalizer block statement without it getting in our way, which could have unexpected side effects otherwise (and will likely return early somewhere). - Stop unwinding so more than one child node of the finalizer BlockStatement is executed if an exception has been thrown previously (which would have called unwind(ScopeType::Try)). Re-throwing as described above ensures we still unwind after the finalizer, if necessary. Also add some tests specifically for try/catch/finally blocks, we didn't have any!
		
			
				
	
	
		
			163 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| test("try/catch without exception", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     try {
 | |
|         tryHasBeenExecuted = true;
 | |
|     } catch (e) {
 | |
|         catchHasBeenExecuted = true;
 | |
|     }
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeFalse();
 | |
| });
 | |
| 
 | |
| test("try/catch with exception in try", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var tryError = Error("Error in try");
 | |
|     try {
 | |
|         tryHasBeenExecuted = true;
 | |
|         throw tryError;
 | |
|         expect().fail();
 | |
|     } catch (e) {
 | |
|         catchHasBeenExecuted = true;
 | |
|         expect(e).toBe(tryError);
 | |
|     }
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch with exception in try and catch", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var tryError = Error("Error in try");
 | |
|     var catchError = Error("Error in catch");
 | |
|     expect(() => {
 | |
|         try {
 | |
|             tryHasBeenExecuted = true;
 | |
|             throw tryError;
 | |
|             expect().fail();
 | |
|         } catch (e) {
 | |
|             catchHasBeenExecuted = true;
 | |
|             expect(e).toBe(tryError);
 | |
|             throw catchError;
 | |
|             expect().fail();
 | |
|         }
 | |
|     }).toThrow(Error, "Error in catch");
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch/finally without exception", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var finallyHasBeenExecuted = false;
 | |
|     try {
 | |
|         tryHasBeenExecuted = true;
 | |
|     } catch (e) {
 | |
|         catchHasBeenExecuted = true;
 | |
|     } finally {
 | |
|         finallyHasBeenExecuted = true;
 | |
|     }
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeFalse();
 | |
|     expect(finallyHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch/finally with exception in try and catch", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var finallyHasBeenExecuted = false;
 | |
|     var tryError = Error("Error in try");
 | |
|     var catchError = Error("Error in catch");
 | |
|     expect(() => {
 | |
|         try {
 | |
|             tryHasBeenExecuted = true;
 | |
|             throw tryError;
 | |
|             expect().fail();
 | |
|         } catch (e) {
 | |
|             catchHasBeenExecuted = true;
 | |
|             expect(e).toBe(tryError);
 | |
|             throw catchError;
 | |
|             expect().fail();
 | |
|         } finally {
 | |
|             finallyHasBeenExecuted = true;
 | |
|         }
 | |
|     }).toThrow(Error, "Error in catch");
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeTrue();
 | |
|     expect(finallyHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch/finally with exception in finally", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var finallyHasBeenExecuted = false;
 | |
|     var finallyError = Error("Error in finally");
 | |
|     expect(() => {
 | |
|         try {
 | |
|             tryHasBeenExecuted = true;
 | |
|         } catch (e) {
 | |
|             catchHasBeenExecuted = true;
 | |
|         } finally {
 | |
|             finallyHasBeenExecuted = true;
 | |
|             throw finallyError;
 | |
|             expect().fail();
 | |
|         }
 | |
|     }).toThrow(Error, "Error in finally");
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeFalse();
 | |
|     expect(finallyHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch/finally with exception in try and finally", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var finallyHasBeenExecuted = false;
 | |
|     var tryError = Error("Error in try");
 | |
|     var finallyError = Error("Error in finally");
 | |
|     expect(() => {
 | |
|         try {
 | |
|             tryHasBeenExecuted = true;
 | |
|             throw tryError;
 | |
|             expect().fail();
 | |
|         } catch (e) {
 | |
|             catchHasBeenExecuted = true;
 | |
|             expect(e).toBe(tryError);
 | |
|         } finally {
 | |
|             finallyHasBeenExecuted = true;
 | |
|             throw finallyError;
 | |
|             expect().fail();
 | |
|         }
 | |
|     }).toThrow(Error, "Error in finally");
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeTrue();
 | |
|     expect(finallyHasBeenExecuted).toBeTrue();
 | |
| });
 | |
| 
 | |
| test("try/catch/finally with exception in try, catch and finally", () => {
 | |
|     var tryHasBeenExecuted = false;
 | |
|     var catchHasBeenExecuted = false;
 | |
|     var finallyHasBeenExecuted = false;
 | |
|     var tryError = Error("Error in try");
 | |
|     var catchError = Error("Error in catch");
 | |
|     var finallyError = Error("Error in finally");
 | |
|     expect(() => {
 | |
|         try {
 | |
|             tryHasBeenExecuted = true;
 | |
|             throw tryError;
 | |
|             expect().fail();
 | |
|         } catch (e) {
 | |
|             catchHasBeenExecuted = true;
 | |
|             expect(e).toBe(tryError);
 | |
|             throw catchError;
 | |
|             expect().fail();
 | |
|         } finally {
 | |
|             finallyHasBeenExecuted = true;
 | |
|             throw finallyError;
 | |
|             expect().fail();
 | |
|         }
 | |
|     }).toThrow(Error, "Error in finally");
 | |
|     expect(tryHasBeenExecuted).toBeTrue();
 | |
|     expect(catchHasBeenExecuted).toBeTrue();
 | |
|     expect(finallyHasBeenExecuted).toBeTrue();
 | |
| });
 |