1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 22:37:35 +00:00

LibJS: Remove GlobalObject from execute() and related AST functions

This is a continuation of the previous four commits.

Passing a global object here is largely redundant, we definitely need
the interpreter but can get the VM and (later) current active realm from
there - and also the global object while we still need it, although I'd
like to remove Interpreter::global_object() in the future.

This now matches the bytecode interpreter's execute_impl() functions.
This commit is contained in:
Linus Groh 2022-08-16 19:28:17 +01:00
parent e992a9f469
commit 5398dcc55e
10 changed files with 409 additions and 357 deletions

View file

@ -712,7 +712,7 @@ ThrowCompletionOr<Value> perform_eval(GlobalObject& global_object, Value x, Call
eval_result = result;
} else {
auto& ast_interpreter = vm.interpreter();
eval_result = TRY(program->execute(ast_interpreter, global_object));
eval_result = TRY(program->execute(ast_interpreter));
}
// 30. If result.[[Type]] is normal and result.[[Value]] is empty, then

View file

@ -451,7 +451,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
// Resulting value is in the accumulator.
argument_value = value_and_frame.frame->registers.at(0);
} else if (interpreter) {
argument_value = TRY(parameter.default_value->execute(*interpreter, global_object)).release_value();
argument_value = TRY(parameter.default_value->execute(*interpreter)).release_value();
}
} else {
argument_value = js_undefined();
@ -730,7 +730,7 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
// 3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
auto* execution_steps = NativeFunction::create(realm, "", [&async_body, &promise_capability](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> {
// a. Let result be the result of evaluating asyncBody.
auto result = async_body->execute(vm.interpreter(), global_object);
auto result = async_body->execute(vm.interpreter());
// b. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
@ -862,7 +862,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
TRY(function_declaration_instantiation(ast_interpreter));
// 2. Return the result of evaluating FunctionStatementList.
return m_ecmascript_code->execute(*ast_interpreter, global_object);
return m_ecmascript_code->execute(*ast_interpreter);
}
// AsyncFunctionBody : FunctionBody
else if (m_kind == FunctionKind::Async) {

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Interpreter.h>
#include <LibJS/Lexer.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/AbstractOperations.h>
@ -173,9 +174,12 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
// 17. If result.[[Type]] is normal, then
if (!eval_result.is_throw_completion()) {
// FIXME: Remove once everything uses the VM's current realm.
auto eval_realm_interpreter = Interpreter::create_with_existing_realm(eval_realm);
// TODO: Optionally use bytecode interpreter?
// a. Set result to the result of evaluating body.
result = program->execute(vm.interpreter(), eval_realm.global_object());
result = program->execute(*eval_realm_interpreter);
}
// 18. If result.[[Type]] is normal and result.[[Value]] is empty, then

View file

@ -235,23 +235,23 @@ Symbol* VM::get_global_symbol(String const& description)
return new_global_symbol;
}
ThrowCompletionOr<Value> VM::named_evaluation_if_anonymous_function(GlobalObject& global_object, ASTNode const& expression, FlyString const& name)
ThrowCompletionOr<Value> VM::named_evaluation_if_anonymous_function(ASTNode const& expression, FlyString const& name)
{
// 8.3.3 Static Semantics: IsAnonymousFunctionDefinition ( expr ), https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition
// And 8.3.5 Runtime Semantics: NamedEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-namedevaluation
if (is<FunctionExpression>(expression)) {
auto& function = static_cast<FunctionExpression const&>(expression);
if (!function.has_name()) {
return function.instantiate_ordinary_function_expression(interpreter(), global_object, name);
return function.instantiate_ordinary_function_expression(interpreter(), name);
}
} else if (is<ClassExpression>(expression)) {
auto& class_expression = static_cast<ClassExpression const&>(expression);
if (!class_expression.has_name()) {
return TRY(class_expression.class_definition_evaluation(interpreter(), global_object, {}, name));
return TRY(class_expression.class_definition_evaluation(interpreter(), {}, name));
}
}
return TRY(expression.execute(interpreter(), global_object)).release_value();
return TRY(expression.execute(interpreter())).release_value();
}
// 13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation
@ -327,7 +327,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
if (auto identifier_ptr = property.name.get_pointer<NonnullRefPtr<Identifier>>()) {
assignment_target = TRY(resolve_binding((*identifier_ptr)->string(), environment));
} else if (auto member_ptr = property.alias.get_pointer<NonnullRefPtr<MemberExpression>>()) {
assignment_target = TRY((*member_ptr)->to_reference(interpreter(), global_object));
assignment_target = TRY((*member_ptr)->to_reference(interpreter()));
} else {
VERIFY_NOT_REACHED();
}
@ -348,7 +348,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
return identifier->string();
},
[&](NonnullRefPtr<Expression> const& expression) -> ThrowCompletionOr<PropertyKey> {
auto result = TRY(expression->execute(interpreter(), global_object)).release_value();
auto result = TRY(expression->execute(interpreter())).release_value();
return result.to_property_key(global_object);
}));
@ -361,7 +361,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
auto value_to_assign = TRY(object->get(name));
if (property.initializer && value_to_assign.is_undefined()) {
value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, identifier.string()));
value_to_assign = TRY(named_evaluation_if_anonymous_function(*property.initializer, identifier.string()));
}
if (!environment)
@ -378,15 +378,15 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
},
[&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
[&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
return TRY(member_expression->to_reference(interpreter(), global_object));
return TRY(member_expression->to_reference(interpreter()));
}));
auto value_to_assign = TRY(object->get(name));
if (property.initializer && value_to_assign.is_undefined()) {
if (auto* identifier_ptr = property.alias.get_pointer<NonnullRefPtr<Identifier>>())
value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, (*identifier_ptr)->string()));
value_to_assign = TRY(named_evaluation_if_anonymous_function(*property.initializer, (*identifier_ptr)->string()));
else
value_to_assign = TRY(property.initializer->execute(interpreter(), global_object)).release_value();
value_to_assign = TRY(property.initializer->execute(interpreter())).release_value();
}
if (auto* binding_ptr = property.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {
@ -421,7 +421,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
},
[&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
[&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
return TRY(member_expression->to_reference(interpreter(), global_object));
return TRY(member_expression->to_reference(interpreter()));
}));
// BindingRestElement : ... BindingIdentifier
@ -520,9 +520,9 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
if (value.is_undefined() && entry.initializer) {
VERIFY(!entry.is_rest);
if (auto* identifier_ptr = entry.alias.get_pointer<NonnullRefPtr<Identifier>>())
value = TRY(named_evaluation_if_anonymous_function(global_object, *entry.initializer, (*identifier_ptr)->string()));
value = TRY(named_evaluation_if_anonymous_function(*entry.initializer, (*identifier_ptr)->string()));
else
value = TRY(entry.initializer->execute(interpreter(), global_object)).release_value();
value = TRY(entry.initializer->execute(interpreter())).release_value();
}
if (auto* binding_ptr = entry.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {

View file

@ -203,7 +203,7 @@ public:
ThrowCompletionOr<void> binding_initialization(FlyString const& target, Value value, Environment* environment, GlobalObject& global_object);
ThrowCompletionOr<void> binding_initialization(NonnullRefPtr<BindingPattern> const& target, Value value, Environment* environment, GlobalObject& global_object);
ThrowCompletionOr<Value> named_evaluation_if_anonymous_function(GlobalObject& global_object, ASTNode const& expression, FlyString const& name);
ThrowCompletionOr<Value> named_evaluation_if_anonymous_function(ASTNode const& expression, FlyString const& name);
void save_execution_context_stack();
void restore_execution_context_stack();