Browse Source

LibJS: Replace GlobalObject with VM in Reference AOs [Part 6/19]

Linus Groh 2 years ago
parent
commit
ae9e031f56

+ 2 - 2
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::TypeError>(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();
 }

+ 31 - 32
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::ThisAndCallee> 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::ThisAndCallee> 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<ForInOfHeadState> for_in_of_head_execute(Interpreter& interpreter, Variant<NonnullRefPtr<ASTNode>, NonnullRefPtr<BindingPattern>> lhs, Expression const& rhs)
 {
-    auto& global_object = interpreter.global_object();
     auto& vm = interpreter.vm();
 
     ForInOfHeadState state(lhs);
@@ -982,7 +981,7 @@ static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& i
                 auto& binding_id = variable.target().get<NonnullRefPtr<Identifier>>()->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<Reference> 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<Reference> 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<ECMAScriptFunctionObject*> 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 <Expression>.
     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<BindingPattern> const& pattern) -> ThrowCompletionOr<void> {
                     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<NonnullRefPtr<Identifier>>());
             auto& identifier = declarator.target().get<NonnullRefPtr<Identifier>>();
             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::ReferenceAndValue> 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::ReferenceAndValue> 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));
         }
     }
 

+ 14 - 11
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -287,35 +287,38 @@ ThrowCompletionOr<void> ConcatString::execute_impl(Bytecode::Interpreter& interp
 
 ThrowCompletionOr<void> GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
 {
+    auto& vm = interpreter.vm();
+
     auto get_reference = [&]() -> ThrowCompletionOr<Reference> {
         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<void> 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<void> 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<void> 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<void> 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<void> 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.

+ 1 - 1
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp

@@ -229,7 +229,7 @@ ThrowCompletionOr<void> 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();

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -463,9 +463,9 @@ ThrowCompletionOr<void> 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<NonnullRefPtr<BindingPattern> const&, decltype(param)>) {
                     // Here the difference from hasDuplicates is important
                     return vm.binding_initialization(param, argument_value, used_environment, global_object);

+ 11 - 15
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<void> Reference::put_value(GlobalObject& global_object, Value value)
+ThrowCompletionOr<void> Reference::put_value(VM& vm, Value value)
 {
-    auto& vm = global_object.vm();
-
     // 1. ReturnIfAbrupt(V).
     // 2. ReturnIfAbrupt(W).
 
@@ -28,9 +26,11 @@ ThrowCompletionOr<void> 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<void> 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<ReferenceError>(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<Value> Reference::get_value(GlobalObject& global_object) const
+ThrowCompletionOr<Value> 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<Value> 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<bool> Reference::delete_(GlobalObject& global_object)
+ThrowCompletionOr<bool> 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<bool> 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<void> Reference::initialize_referenced_binding(GlobalObject& global_object, Value value) const
+ThrowCompletionOr<void> 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);

+ 5 - 5
Userland/Libraries/LibJS/Runtime/Reference.h

@@ -121,11 +121,11 @@ public:
         return m_base_type == BaseType::Environment;
     }
 
-    ThrowCompletionOr<void> initialize_referenced_binding(GlobalObject& global_object, Value value) const;
+    ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value) const;
 
-    ThrowCompletionOr<void> put_value(GlobalObject&, Value);
-    ThrowCompletionOr<Value> get_value(GlobalObject&) const;
-    ThrowCompletionOr<bool> delete_(GlobalObject&);
+    ThrowCompletionOr<void> put_value(VM&, Value);
+    ThrowCompletionOr<Value> get_value(VM&) const;
+    ThrowCompletionOr<bool> delete_(VM&);
 
     String to_string() const;
 
@@ -134,7 +134,7 @@ public:
     Optional<EnvironmentCoordinate> 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 {

+ 19 - 8
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -338,9 +338,9 @@ ThrowCompletionOr<void> 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<void> 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<void> 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<void> VM::property_binding_initialization(BindingPattern const
 // 8.5.3 Runtime Semantics: IteratorBindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-iteratorbindinginitialization
 ThrowCompletionOr<void> 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<void> VM::iterator_binding_initialization(BindingPattern const
         } else if (!entry.alias.has<Empty>()) {
             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<FunctionEnvironment>(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())

+ 2 - 0
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();

+ 1 - 1
Userland/Utilities/js.cpp

@@ -1726,7 +1726,7 @@ ErrorOr<int> 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();