summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/AST.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-07-04 17:22:27 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-04 18:56:08 +0200
commitd114ba4c4e52d52755ad8b874e3ab4ec67b794e7 (patch)
tree95bb7207c60e67e3c0ee923dfda0bd6e86736355 /Userland/Libraries/LibJS/AST.cpp
parentdce18958b6103cf77705046e1dc8a51085b31bfa (diff)
downloadserenity-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.cpp32
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