From ae9e031f567937db0119ac4d649ae5ccf24e41f7 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 21 Aug 2022 15:39:13 +0100 Subject: [PATCH] LibJS: Replace GlobalObject with VM in Reference AOs [Part 6/19] --- Tests/LibJS/test-js.cpp | 4 +- Userland/Libraries/LibJS/AST.cpp | 63 +++++++++---------- Userland/Libraries/LibJS/Bytecode/Op.cpp | 25 ++++---- .../LibJS/Runtime/AbstractOperations.cpp | 2 +- .../Runtime/ECMAScriptFunctionObject.cpp | 4 +- .../Libraries/LibJS/Runtime/Reference.cpp | 26 ++++---- Userland/Libraries/LibJS/Runtime/Reference.h | 10 +-- Userland/Libraries/LibJS/Runtime/VM.cpp | 27 +++++--- Userland/Libraries/LibJS/Runtime/VM.h | 2 + Userland/Utilities/js.cpp | 2 +- 10 files changed, 88 insertions(+), 77 deletions(-) diff --git a/Tests/LibJS/test-js.cpp b/Tests/LibJS/test-js.cpp index 0780590ae8..f34bb9b584 100644 --- a/Tests/LibJS/test-js.cpp +++ b/Tests/LibJS/test-js.cpp @@ -66,13 +66,13 @@ TESTJS_GLOBAL_FUNCTION(mark_as_garbage, markAsGarbage) auto reference = TRY(vm.resolve_binding(variable_name.string(), outer_environment.value()->lexical_environment)); - auto value = TRY(reference.get_value(global_object)); + auto value = TRY(reference.get_value(vm)); if (!can_be_held_weakly(value)) return vm.throw_completion(JS::ErrorType::CannotBeHeldWeakly, String::formatted("Variable with name {}", variable_name.string())); vm.heap().uproot_cell(&value.as_cell()); - TRY(reference.delete_(global_object)); + TRY(reference.delete_(vm)); return JS::js_undefined(); } diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 184419af7c..97102e18e5 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -337,10 +337,10 @@ Completion ExpressionStatement::execute(Interpreter& interpreter) const // TODO: This shouldn't exist. Refactor into EvaluateCall. ThrowCompletionOr CallExpression::compute_this_and_callee(Interpreter& interpreter, Reference const& callee_reference) const { - auto& global_object = interpreter.global_object(); + auto& vm = interpreter.vm(); if (callee_reference.is_property_reference()) { auto this_value = callee_reference.get_this_value(); - auto callee = TRY(callee_reference.get_value(global_object)); + auto callee = TRY(callee_reference.get_value(vm)); return ThisAndCallee { this_value, callee }; } @@ -356,7 +356,7 @@ ThrowCompletionOr CallExpression::compute_this_an this_value, callee_reference.is_unresolvable() ? TRY(m_callee->execute(interpreter)).release_value() - : TRY(callee_reference.get_value(global_object)) + : TRY(callee_reference.get_value(vm)) }; } @@ -929,9 +929,9 @@ struct ForInOfHeadState { if (!destructuring) { VERIFY(lhs_reference.has_value()); if (lhs_kind == LexicalBinding) - return lhs_reference->initialize_referenced_binding(global_object, next_value); + return lhs_reference->initialize_referenced_binding(vm, next_value); else - return lhs_reference->put_value(global_object, next_value); + return lhs_reference->put_value(vm, next_value); } // j. Else, @@ -956,7 +956,6 @@ struct ForInOfHeadState { // For the same reason we also skip step 6 and 7 of ForIn/OfHeadEvaluation as this is done by the appropriate for loop type. static ThrowCompletionOr for_in_of_head_execute(Interpreter& interpreter, Variant, NonnullRefPtr> lhs, Expression const& rhs) { - auto& global_object = interpreter.global_object(); auto& vm = interpreter.vm(); ForInOfHeadState state(lhs); @@ -982,7 +981,7 @@ static ThrowCompletionOr for_in_of_head_execute(Interpreter& i auto& binding_id = variable.target().get>()->string(); auto reference = TRY(interpreter.vm().resolve_binding(binding_id)); auto result = TRY(interpreter.vm().named_evaluation_if_anonymous_function(*variable.init(), binding_id)); - TRY(reference.put_value(global_object, result)); + TRY(reference.put_value(vm, result)); } } else { state.lhs_kind = ForInOfHeadState::LexicalBinding; @@ -1444,7 +1443,7 @@ ThrowCompletionOr MemberExpression::to_reference(Interpreter& interpr Value base_value; if (base_reference.is_valid_reference()) - base_value = TRY(base_reference.get_value(global_object)); + base_value = TRY(base_reference.get_value(vm)); else base_value = TRY(m_object->execute(interpreter)).release_value(); @@ -1485,12 +1484,11 @@ ThrowCompletionOr MemberExpression::to_reference(Interpreter& interpr Completion UnaryExpression::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; - auto& global_object = interpreter.global_object(); - auto& vm = interpreter.vm(); + if (m_op == UnaryOp::Delete) { auto reference = TRY(m_lhs->to_reference(interpreter)); - return Value(TRY(reference.delete_(global_object))); + return Value(TRY(reference.delete_(vm))); } Value lhs_result; @@ -1500,7 +1498,7 @@ Completion UnaryExpression::execute(Interpreter& interpreter) const if (reference.is_unresolvable()) lhs_result = js_undefined(); else - lhs_result = TRY(reference.get_value(global_object)); + lhs_result = TRY(reference.get_value(vm)); VERIFY(!lhs_result.is_empty()); } else { // 1. Let expr be the result of evaluating UnaryExpression. @@ -1853,7 +1851,7 @@ ThrowCompletionOr ClassExpression::class_definition_e auto reference = TRY(m_super_class->to_reference(interpreter)); if (reference.is_valid_reference()) { - super_class = TRY(reference.get_value(global_object)); + super_class = TRY(reference.get_value(vm)); } else { super_class = TRY(m_super_class->execute(interpreter)).release_value(); } @@ -2543,14 +2541,14 @@ void ForAwaitOfStatement::dump(int indent) const Completion Identifier::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; - auto& global_object = interpreter.global_object(); + auto& vm = interpreter.vm(); // 1. Return ? ResolveBinding(StringValue of Identifier). - auto reference = TRY(interpreter.vm().resolve_binding(m_string)); + auto reference = TRY(vm.resolve_binding(m_string)); // NOTE: The spec wants us to return the reference directly; this is not possible with ASTNode::execute() (short of letting it return a variant). // So, instead of calling GetValue at the call site, we do it here. - return TRY(reference.get_value(global_object)); + return TRY(reference.get_value(vm)); } void Identifier::dump(int indent) const @@ -2631,7 +2629,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter) const } // e. Perform ? PutValue(lref, rval). - TRY(reference.put_value(global_object, rhs_result)); + TRY(reference.put_value(vm, rhs_result)); // f. Return rval. return rhs_result; @@ -2656,7 +2654,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter) const auto reference = TRY(lhs_expression.to_reference(interpreter)); // 2. Let lval be ? GetValue(lref). - auto lhs_result = TRY(reference.get_value(global_object)); + auto lhs_result = TRY(reference.get_value(vm)); // AssignmentExpression : LeftHandSideExpression {&&=, ||=, ??=} AssignmentExpression if (m_op == AssignmentOp::AndAssignment || m_op == AssignmentOp::OrAssignment || m_op == AssignmentOp::NullishAssignment) { @@ -2704,7 +2702,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter) const } // 7. Perform ? PutValue(lref, rval). - TRY(reference.put_value(global_object, rhs_result)); + TRY(reference.put_value(vm, rhs_result)); // 8. Return rval. return rhs_result; @@ -2764,7 +2762,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter) const } // 8. Perform ? PutValue(lref, r). - TRY(reference.put_value(global_object, rhs_result)); + TRY(reference.put_value(vm, rhs_result)); // 9. Return r. return rhs_result; @@ -2777,14 +2775,13 @@ Completion AssignmentExpression::execute(Interpreter& interpreter) const Completion UpdateExpression::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; - auto& global_object = interpreter.global_object(); auto& vm = interpreter.vm(); // 1. Let expr be the result of evaluating . auto reference = TRY(m_argument->to_reference(interpreter)); // 2. Let oldValue be ? ToNumeric(? GetValue(expr)). - auto old_value = TRY(reference.get_value(global_object)); + auto old_value = TRY(reference.get_value(vm)); old_value = TRY(old_value.to_numeric(vm)); Value new_value; @@ -2820,7 +2817,7 @@ Completion UpdateExpression::execute(Interpreter& interpreter) const } // 5. Perform ? PutValue(expr, newValue). - TRY(reference.put_value(global_object, new_value)); + TRY(reference.put_value(vm, new_value)); // 6. Return newValue. // 6. Return oldValue. @@ -2918,6 +2915,7 @@ Completion VariableDeclaration::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; auto& global_object = interpreter.global_object(); + auto& vm = interpreter.vm(); for (auto& declarator : m_declarations) { if (auto* init = declarator.init()) { @@ -2928,22 +2926,22 @@ Completion VariableDeclaration::execute(Interpreter& interpreter) const VERIFY(!initializer_result.is_empty()); if (m_declaration_kind == DeclarationKind::Var) - return reference.put_value(global_object, initializer_result); + return reference.put_value(vm, initializer_result); else - return reference.initialize_referenced_binding(global_object, initializer_result); + return reference.initialize_referenced_binding(vm, initializer_result); }, [&](NonnullRefPtr const& pattern) -> ThrowCompletionOr { auto initializer_result = TRY(init->execute(interpreter)).release_value(); Environment* environment = m_declaration_kind == DeclarationKind::Var ? nullptr : interpreter.lexical_environment(); - return interpreter.vm().binding_initialization(pattern, initializer_result, environment, global_object); + return vm.binding_initialization(pattern, initializer_result, environment, global_object); })); } else if (m_declaration_kind != DeclarationKind::Var) { VERIFY(declarator.target().has>()); auto& identifier = declarator.target().get>(); auto reference = TRY(identifier->to_reference(interpreter)); - TRY(reference.initialize_referenced_binding(global_object, js_undefined())); + TRY(reference.initialize_referenced_binding(vm, js_undefined())); } } return normal_completion({}); @@ -3135,10 +3133,10 @@ String MemberExpression::to_string_approximation() const Completion MemberExpression::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; - auto& global_object = interpreter.global_object(); + auto& vm = interpreter.vm(); auto reference = TRY(to_reference(interpreter)); - return TRY(reference.get_value(global_object)); + return TRY(reference.get_value(vm)); } bool MemberExpression::ends_in_private_name() const @@ -3185,11 +3183,12 @@ void OptionalChain::dump(int indent) const ThrowCompletionOr OptionalChain::to_reference_and_value(Interpreter& interpreter) const { - auto& global_object = interpreter.global_object(); + auto& vm = interpreter.vm(); + auto base_reference = TRY(m_base->to_reference(interpreter)); auto base = base_reference.is_unresolvable() ? TRY(m_base->execute(interpreter)).release_value() - : TRY(base_reference.get_value(global_object)); + : TRY(base_reference.get_value(vm)); for (auto& reference : m_references) { auto is_optional = reference.visit([](auto& ref) { return ref.mode; }) == Mode::Optional; @@ -3225,7 +3224,7 @@ ThrowCompletionOr OptionalChain::to_reference_ base = TRY(expression->execute(interpreter)).release_value(); } else { base_reference = TRY(expression->to_reference(interpreter)); - base = TRY(base_reference.get_value(global_object)); + base = TRY(base_reference.get_value(vm)); } } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index a85d7fdff7..310ed50253 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -287,35 +287,38 @@ ThrowCompletionOr ConcatString::execute_impl(Bytecode::Interpreter& interp ThrowCompletionOr GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const { + auto& vm = interpreter.vm(); + auto get_reference = [&]() -> ThrowCompletionOr { auto const& string = interpreter.current_executable().get_identifier(m_identifier); if (m_cached_environment_coordinate.has_value()) { - auto* environment = interpreter.vm().running_execution_context().lexical_environment; + auto* environment = vm.running_execution_context().lexical_environment; for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i) environment = environment->outer_environment(); VERIFY(environment); VERIFY(environment->is_declarative_environment()); if (!environment->is_permanently_screwed_by_eval()) { - return Reference { *environment, string, interpreter.vm().in_strict_mode(), m_cached_environment_coordinate }; + return Reference { *environment, string, vm.in_strict_mode(), m_cached_environment_coordinate }; } m_cached_environment_coordinate = {}; } - auto reference = TRY(interpreter.vm().resolve_binding(string)); + auto reference = TRY(vm.resolve_binding(string)); if (reference.environment_coordinate().has_value()) m_cached_environment_coordinate = reference.environment_coordinate(); return reference; }; auto reference = TRY(get_reference()); - interpreter.accumulator() = TRY(reference.get_value(interpreter.global_object())); + interpreter.accumulator() = TRY(reference.get_value(vm)); return {}; } ThrowCompletionOr DeleteVariable::execute_impl(Bytecode::Interpreter& interpreter) const { + auto& vm = interpreter.vm(); auto const& string = interpreter.current_executable().get_identifier(m_identifier); - auto reference = TRY(interpreter.vm().resolve_binding(string)); - interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object()))); + auto reference = TRY(vm.resolve_binding(string)); + interpreter.accumulator() = Value(TRY(reference.delete_(vm))); return {}; } @@ -383,10 +386,10 @@ ThrowCompletionOr SetVariable::execute_impl(Bytecode::Interpreter& interpr auto reference = TRY(vm.resolve_binding(name, environment)); switch (m_initialization_mode) { case InitializationMode::Initialize: - TRY(reference.initialize_referenced_binding(interpreter.global_object(), interpreter.accumulator())); + TRY(reference.initialize_referenced_binding(vm, interpreter.accumulator())); break; case InitializationMode::Set: - TRY(reference.put_value(interpreter.global_object(), interpreter.accumulator())); + TRY(reference.put_value(vm, interpreter.accumulator())); break; case InitializationMode::InitializeOrSet: VERIFY(reference.is_environment_reference()); @@ -421,7 +424,7 @@ ThrowCompletionOr DeleteById::execute_impl(Bytecode::Interpreter& interpre auto const& identifier = interpreter.current_executable().get_identifier(m_property); bool strict = vm.in_strict_mode(); auto reference = Reference { object, identifier, {}, strict }; - interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object()))); + interpreter.accumulator() = Value(TRY(reference.delete_(vm))); return {}; }; @@ -668,7 +671,7 @@ ThrowCompletionOr DeleteByValue::execute_impl(Bytecode::Interpreter& inter auto property_key = TRY(interpreter.accumulator().to_property_key(vm)); bool strict = vm.in_strict_mode(); auto reference = Reference { object, property_key, {}, strict }; - interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object()))); + interpreter.accumulator() = Value(TRY(reference.delete_(vm))); return {}; } @@ -816,7 +819,7 @@ ThrowCompletionOr TypeofVariable::execute_impl(Bytecode::Interpreter& inte } // 3. Set val to ? GetValue(val). - auto value = TRY(reference.get_value(interpreter.global_object())); + auto value = TRY(reference.get_value(vm)); // 4. NOTE: This step is replaced in section B.3.6.3. // 5. Return a String according to Table 41. diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 6a6a289ad8..7ba441a1aa 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -229,7 +229,7 @@ ThrowCompletionOr initialize_bound_name(GlobalObject& global_object, FlySt auto lhs = TRY(vm.resolve_binding(name)); // b. Return ? PutValue(lhs, value). - return TRY(lhs.put_value(global_object, value)); + return TRY(lhs.put_value(vm, value)); } VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index c1fcfef03a..d06f8c14c0 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -463,9 +463,9 @@ ThrowCompletionOr ECMAScriptFunctionObject::function_declaration_instantia Reference reference = TRY(vm.resolve_binding(param, used_environment)); // Here the difference from hasDuplicates is important if (has_duplicates) - return reference.put_value(global_object, argument_value); + return reference.put_value(vm, argument_value); else - return reference.initialize_referenced_binding(global_object, argument_value); + return reference.initialize_referenced_binding(vm, argument_value); } else if (IsSame const&, decltype(param)>) { // Here the difference from hasDuplicates is important return vm.binding_initialization(param, argument_value, used_environment, global_object); diff --git a/Userland/Libraries/LibJS/Runtime/Reference.cpp b/Userland/Libraries/LibJS/Runtime/Reference.cpp index ccaeacfa6a..a5d1c107b6 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.cpp +++ b/Userland/Libraries/LibJS/Runtime/Reference.cpp @@ -13,10 +13,8 @@ namespace JS { // 6.2.4.6 PutValue ( V, W ), https://tc39.es/ecma262/#sec-putvalue -ThrowCompletionOr Reference::put_value(GlobalObject& global_object, Value value) +ThrowCompletionOr Reference::put_value(VM& vm, Value value) { - auto& vm = global_object.vm(); - // 1. ReturnIfAbrupt(V). // 2. ReturnIfAbrupt(W). @@ -28,9 +26,11 @@ ThrowCompletionOr Reference::put_value(GlobalObject& global_object, Value if (is_unresolvable()) { // a. If V.[[Strict]] is true, throw a ReferenceError exception. if (m_strict) - return throw_reference_error(global_object); + return throw_reference_error(vm); // b. Let globalObj be GetGlobalObject(). + auto& global_object = vm.get_global_object(); + // c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false). TRY(global_object.set(m_name, value, Object::ShouldThrowExceptions::No)); @@ -74,9 +74,8 @@ ThrowCompletionOr Reference::put_value(GlobalObject& global_object, Value return m_base_environment->set_mutable_binding(vm, m_name.as_string(), value, m_strict); } -Completion Reference::throw_reference_error(GlobalObject& global_object) const +Completion Reference::throw_reference_error(VM& vm) const { - auto& vm = global_object.vm(); if (!m_name.is_valid()) return vm.throw_completion(ErrorType::ReferenceUnresolvable); else @@ -84,16 +83,17 @@ Completion Reference::throw_reference_error(GlobalObject& global_object) const } // 6.2.4.5 GetValue ( V ), https://tc39.es/ecma262/#sec-getvalue -ThrowCompletionOr Reference::get_value(GlobalObject& global_object) const +ThrowCompletionOr Reference::get_value(VM& vm) const { - auto& vm = global_object.vm(); + auto& realm = *vm.current_realm(); + auto& global_object = realm.global_object(); // 1. ReturnIfAbrupt(V). // 2. If V is not a Reference Record, return V. // 3. If IsUnresolvableReference(V) is true, throw a ReferenceError exception. if (!is_valid_reference() || is_unresolvable()) - return throw_reference_error(global_object); + return throw_reference_error(vm); // 4. If IsPropertyReference(V) is true, then if (is_property_reference()) { @@ -145,7 +145,7 @@ ThrowCompletionOr Reference::get_value(GlobalObject& global_object) const } // 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation -ThrowCompletionOr Reference::delete_(GlobalObject& global_object) +ThrowCompletionOr Reference::delete_(VM& vm) { // 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation // UnaryExpression : delete UnaryExpression @@ -163,8 +163,6 @@ ThrowCompletionOr Reference::delete_(GlobalObject& global_object) return true; } - auto& vm = global_object.vm(); - // 5. If IsPropertyReference(ref) is true, then if (is_property_reference()) { // a. Assert: IsPrivateReference(ref) is false. @@ -235,10 +233,8 @@ String Reference::to_string() const } // 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty -ThrowCompletionOr Reference::initialize_referenced_binding(GlobalObject& global_object, Value value) const +ThrowCompletionOr Reference::initialize_referenced_binding(VM& vm, Value value) const { - auto& vm = global_object.vm(); - VERIFY(!is_unresolvable()); VERIFY(m_base_type == BaseType::Environment); return m_base_environment->initialize_binding(vm, m_name.as_string(), value); diff --git a/Userland/Libraries/LibJS/Runtime/Reference.h b/Userland/Libraries/LibJS/Runtime/Reference.h index ecd23e660a..5e8468b3c4 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.h +++ b/Userland/Libraries/LibJS/Runtime/Reference.h @@ -121,11 +121,11 @@ public: return m_base_type == BaseType::Environment; } - ThrowCompletionOr initialize_referenced_binding(GlobalObject& global_object, Value value) const; + ThrowCompletionOr initialize_referenced_binding(VM&, Value value) const; - ThrowCompletionOr put_value(GlobalObject&, Value); - ThrowCompletionOr get_value(GlobalObject&) const; - ThrowCompletionOr delete_(GlobalObject&); + ThrowCompletionOr put_value(VM&, Value); + ThrowCompletionOr get_value(VM&) const; + ThrowCompletionOr delete_(VM&); String to_string() const; @@ -134,7 +134,7 @@ public: Optional environment_coordinate() const { return m_environment_coordinate; } private: - Completion throw_reference_error(GlobalObject&) const; + Completion throw_reference_error(VM&) const; BaseType m_base_type { BaseType::Unresolvable }; union { diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 7593cf46a9..283370cb94 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -338,9 +338,9 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const TRY(rest_object->copy_data_properties(vm, object, seen_names)); if (!environment) - return assignment_target.put_value(global_object, rest_object); + return assignment_target.put_value(vm, rest_object); else - return assignment_target.initialize_referenced_binding(global_object, rest_object); + return assignment_target.initialize_referenced_binding(vm, rest_object); } auto name = TRY(property.name.visit( @@ -366,9 +366,9 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const } if (!environment) - TRY(reference.put_value(global_object, value_to_assign)); + TRY(reference.put_value(vm, value_to_assign)); else - TRY(reference.initialize_referenced_binding(global_object, value_to_assign)); + TRY(reference.initialize_referenced_binding(vm, value_to_assign)); continue; } @@ -395,9 +395,9 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const } else { VERIFY(reference_to_assign_to.has_value()); if (!environment) - TRY(reference_to_assign_to->put_value(global_object, value_to_assign)); + TRY(reference_to_assign_to->put_value(vm, value_to_assign)); else - TRY(reference_to_assign_to->initialize_referenced_binding(global_object, value_to_assign)); + TRY(reference_to_assign_to->initialize_referenced_binding(vm, value_to_assign)); } } @@ -408,6 +408,7 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const // 8.5.3 Runtime Semantics: IteratorBindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-iteratorbindinginitialization ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const& binding, Iterator& iterator_record, Environment* environment, GlobalObject& global_object) { + auto& vm = *this; auto& realm = *global_object.associated_realm(); // FIXME: this method is nearly identical to destructuring assignment! @@ -531,9 +532,9 @@ ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const } else if (!entry.alias.has()) { VERIFY(assignment_target.has_value()); if (!environment) - TRY(assignment_target->put_value(global_object, value)); + TRY(assignment_target->put_value(vm, value)); else - TRY(assignment_target->initialize_referenced_binding(global_object, value)); + TRY(assignment_target->initialize_referenced_binding(vm, value)); } } @@ -639,6 +640,16 @@ Value VM::get_new_target() return verify_cast(env).new_target(); } +// 9.4.5 GetGlobalObject ( ), https://tc39.es/ecma262/#sec-getglobalobject +GlobalObject& VM::get_global_object() +{ + // 1. Let currentRealm be the current Realm Record. + auto& current_realm = *this->current_realm(); + + // 2. Return currentRealm.[[GlobalObject]]. + return current_realm.global_object(); +} + bool VM::in_strict_mode() const { if (execution_context_stack().is_empty()) diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index f3976931d7..6825ef4adf 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -183,6 +183,8 @@ public: Value get_new_target(); + GlobalObject& get_global_object(); + CommonPropertyNames names; void run_queued_promise_jobs(); diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index 70f6f075b3..93e897403c 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -1726,7 +1726,7 @@ ErrorOr serenity_main(Main::Arguments arguments) auto reference_or_error = g_vm->resolve_binding(variable_name, &global_environment); if (reference_or_error.is_error()) return {}; - auto value_or_error = reference_or_error.value().get_value(interpreter->global_object()); + auto value_or_error = reference_or_error.value().get_value(*g_vm); if (value_or_error.is_error()) return {}; auto variable = value_or_error.value();