diff options
author | Andreas Kling <kling@serenityos.org> | 2021-07-04 17:22:27 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-04 18:56:08 +0200 |
commit | d114ba4c4e52d52755ad8b874e3ab4ec67b794e7 (patch) | |
tree | 95bb7207c60e67e3c0ee923dfda0bd6e86736355 /Userland/Libraries/LibJS/AST.cpp | |
parent | dce18958b6103cf77705046e1dc8a51085b31bfa (diff) | |
download | serenity-d114ba4c4e52d52755ad8b874e3ab4ec67b794e7.zip |
LibJS: Make the `with` statement evaluation follow the spec even more
This was almost entirely up-to-spec already, just missing exception
checks, and we now leave the lexical environment in the modified state
if an exception occurs during statement evaluation.
Diffstat (limited to 'Userland/Libraries/LibJS/AST.cpp')
-rw-r--r-- | Userland/Libraries/LibJS/AST.cpp | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index a971719739..ffc7a2efb3 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -339,23 +339,43 @@ Value IfStatement::execute(Interpreter& interpreter, GlobalObject& global_object return js_undefined(); } +// 14.11.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-with-statement-runtime-semantics-evaluation +// WithStatement : with ( Expression ) Statement Value WithStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const { InterpreterNodeScope node_scope { interpreter, *this }; - auto object_value = m_object->execute(interpreter, global_object); + // 1. Let value be the result of evaluating Expression. + auto value = m_object->execute(interpreter, global_object); + if (interpreter.exception()) + return {}; + + // 2. Let obj be ? ToObject(? GetValue(value)). + auto* object = value.to_object(global_object); + if (interpreter.exception()) + return {}; + + // 3. Let oldEnv be the running execution context's LexicalEnvironment. + auto* old_environment = interpreter.vm().running_execution_context().lexical_environment; + + // 4. Let newEnv be NewObjectEnvironment(obj, true, oldEnv). + auto* new_environment = new_object_environment(*object, true, old_environment); if (interpreter.exception()) return {}; - auto* object = object_value.to_object(global_object); + // 5. Set the running execution context's LexicalEnvironment to newEnv. + interpreter.vm().running_execution_context().lexical_environment = new_environment; + + // 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 {}; - VERIFY(object); + // 7. Set the running execution context's LexicalEnvironment to oldEnv. + interpreter.vm().running_execution_context().lexical_environment = old_environment; - auto* object_environment = new_object_environment(*object, true, interpreter.vm().running_execution_context().lexical_environment); - TemporaryChange<Environment*> scope_change(interpreter.vm().running_execution_context().lexical_environment, object_environment); - return interpreter.execute_statement(global_object, m_body).value_or(js_undefined()); + // 8. Return Completion(UpdateEmpty(C, undefined)). + return result; } Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const |