Skip to content

Commit

Permalink
LibJS: Restore the environment if an exception is thrown in 'with' block
Browse files Browse the repository at this point in the history
  • Loading branch information
davidot authored and linusg committed Sep 8, 2021
1 parent 4175be6 commit db0a48d
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Userland/Libraries/LibJS/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
21 changes: 21 additions & 0 deletions Userland/Libraries/LibJS/Tests/with-basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,31 @@ test("basic with statement functionality", () => {
}

expect(object.bar).toBe(2);
expect(() => foo).toThrowWithMessage(ReferenceError, "'foo' is not defined");

expect(bar).toBe(99);
});

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");
});

0 comments on commit db0a48d

Please sign in to comment.