diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index cfdfec846c..012d369053 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -1376,11 +1376,16 @@ ThrowCompletionOr Expression::to_reference(Interpreter&) const ThrowCompletionOr Identifier::to_reference(Interpreter& interpreter) const { if (m_cached_environment_coordinate.has_value()) { - auto* environment = interpreter.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()); + Environment* environment = nullptr; + if (m_cached_environment_coordinate->index == EnvironmentCoordinate::global_marker) { + environment = &interpreter.vm().current_realm()->global_environment(); + } else { + environment = interpreter.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 }; } diff --git a/Userland/Libraries/LibJS/Runtime/EnvironmentCoordinate.h b/Userland/Libraries/LibJS/Runtime/EnvironmentCoordinate.h index f2ca2b0050..54eb605215 100644 --- a/Userland/Libraries/LibJS/Runtime/EnvironmentCoordinate.h +++ b/Userland/Libraries/LibJS/Runtime/EnvironmentCoordinate.h @@ -14,6 +14,8 @@ namespace JS { struct EnvironmentCoordinate { size_t hops { 0 }; size_t index { 0 }; + + static constexpr size_t global_marker = 0xffffffff; }; } diff --git a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp index ec1dbc729e..5d00a5fdf9 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp @@ -39,8 +39,11 @@ ThrowCompletionOr GlobalEnvironment::get_this_binding(VM&) const } // 9.1.1.4.1 HasBinding ( N ), https://tc39.es/ecma262/#sec-global-environment-records-hasbinding-n -ThrowCompletionOr GlobalEnvironment::has_binding(FlyString const& name, Optional*) const +ThrowCompletionOr GlobalEnvironment::has_binding(FlyString const& name, Optional* out_index) const { + if (out_index) + *out_index = EnvironmentCoordinate::global_marker; + // 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 2. If ! DclRec.HasBinding(N) is true, return true. if (MUST(m_declarative_record->has_binding(name))) diff --git a/Userland/Libraries/LibJS/Runtime/Reference.cpp b/Userland/Libraries/LibJS/Runtime/Reference.cpp index c6bff072ec..9cf9e47af1 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.cpp +++ b/Userland/Libraries/LibJS/Runtime/Reference.cpp @@ -68,7 +68,7 @@ ThrowCompletionOr Reference::put_value(VM& vm, Value value) VERIFY(m_base_environment); // c. Return ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]]) (see 9.1). - if (m_environment_coordinate.has_value()) + if (m_environment_coordinate.has_value() && m_environment_coordinate->index != EnvironmentCoordinate::global_marker) return static_cast(m_base_environment)->set_mutable_binding_direct(vm, m_environment_coordinate->index, value, m_strict); else return m_base_environment->set_mutable_binding(vm, m_name.as_string(), value, m_strict); @@ -138,7 +138,7 @@ ThrowCompletionOr Reference::get_value(VM& vm) const VERIFY(m_base_environment); // c. Return ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]]) (see 9.1). - if (m_environment_coordinate.has_value()) + if (m_environment_coordinate.has_value() && m_environment_coordinate->index != EnvironmentCoordinate::global_marker) return static_cast(m_base_environment)->get_binding_value_direct(vm, m_environment_coordinate->index, m_strict); return m_base_environment->get_binding_value(vm, m_name.as_string(), m_strict); }