diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 80dd4f6448d..658d5b60811 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -379,12 +379,13 @@ Value WithStatement::execute(Interpreter& interpreter, GlobalObject& global_obje // 6. Let C be the result of evaluating Statement. auto result = interpreter.execute_statement(global_object, m_body).value_or(js_undefined()); - if (interpreter.exception()) - return {}; // 7. Set the running execution context's LexicalEnvironment to oldEnv. interpreter.vm().running_execution_context().lexical_environment = old_environment; + if (interpreter.exception()) + return {}; + // 8. Return Completion(UpdateEmpty(C, undefined)). return result; } diff --git a/Userland/Libraries/LibJS/Tests/with-basic.js b/Userland/Libraries/LibJS/Tests/with-basic.js index c2ef01698b4..110c454734c 100644 --- a/Userland/Libraries/LibJS/Tests/with-basic.js +++ b/Userland/Libraries/LibJS/Tests/with-basic.js @@ -15,6 +15,7 @@ test("basic with statement functionality", () => { } expect(object.bar).toBe(2); + expect(() => foo).toThrowWithMessage(ReferenceError, "'foo' is not defined"); expect(bar).toBe(99); }); @@ -22,3 +23,23 @@ test("basic with statement functionality", () => { test("syntax error in strict mode", () => { expect("'use strict'; with (foo) {}").not.toEval(); }); + +test("restores lexical environment even when exception is thrown", () => { + var object = { + foo: 1, + get bar() { + throw Error(); + }, + }; + + try { + with (object) { + expect(foo).toBe(1); + bar; + } + expect().fail(); + } catch (e) { + expect(() => foo).toThrowWithMessage(ReferenceError, "'foo' is not defined"); + } + expect(() => foo).toThrowWithMessage(ReferenceError, "'foo' is not defined"); +});