From 4444bcabde975014de2f13cd3cd7ce4149cee8c3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 7 Oct 2021 00:16:37 +0200 Subject: [PATCH] LibJS: Make Reference aware of DeclarativeEnvironment indices VM::resolve_binding() can now return a Reference that knows the exact binding index if it's pointing into a DeclarativeEnvironment. Reading/writing through the Reference will now use direct environment access when possible. --- Userland/Libraries/LibJS/Runtime/Reference.cpp | 8 +++++++- Userland/Libraries/LibJS/Runtime/Reference.h | 4 +++- Userland/Libraries/LibJS/Runtime/VM.cpp | 6 ++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Reference.cpp b/Userland/Libraries/LibJS/Runtime/Reference.cpp index f2042bd3d7f..b9ec35b37bf 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.cpp +++ b/Userland/Libraries/LibJS/Runtime/Reference.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -48,7 +49,10 @@ void Reference::put_value(GlobalObject& global_object, Value value) VERIFY(m_base_type == BaseType::Environment); VERIFY(m_base_environment); - m_base_environment->set_mutable_binding(global_object, m_name.as_string(), value, m_strict); + if (m_index_in_declarative_environment.has_value()) + static_cast(m_base_environment)->set_mutable_binding_direct(global_object, m_index_in_declarative_environment.value(), value, m_strict); + else + m_base_environment->set_mutable_binding(global_object, m_name.as_string(), value, m_strict); } void Reference::throw_reference_error(GlobalObject& global_object) const @@ -77,6 +81,8 @@ Value Reference::get_value(GlobalObject& global_object) const VERIFY(m_base_type == BaseType::Environment); VERIFY(m_base_environment); + if (m_index_in_declarative_environment.has_value()) + return static_cast(m_base_environment)->get_binding_value_direct(global_object, m_index_in_declarative_environment.value(), m_strict); return m_base_environment->get_binding_value(global_object, m_name.as_string(), m_strict); } diff --git a/Userland/Libraries/LibJS/Runtime/Reference.h b/Userland/Libraries/LibJS/Runtime/Reference.h index 8bd025f8538..6527b9a86e6 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.h +++ b/Userland/Libraries/LibJS/Runtime/Reference.h @@ -44,11 +44,12 @@ public: } } - Reference(Environment& base, FlyString referenced_name, bool strict = false) + Reference(Environment& base, FlyString referenced_name, bool strict = false, Optional index_in_declarative_environment = {}) : m_base_type(BaseType::Environment) , m_base_environment(&base) , m_name(move(referenced_name)) , m_strict(strict) + , m_index_in_declarative_environment(move(index_in_declarative_environment)) { } @@ -129,6 +130,7 @@ private: PropertyName m_name; Value m_this_value; bool m_strict { false }; + Optional m_index_in_declarative_environment; }; } diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 82e19cdea66..0bd7dcf8518 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -442,12 +442,14 @@ Reference VM::get_identifier_reference(Environment* environment, FlyString name, // a. Return the Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }. return Reference { Reference::BaseType::Unresolvable, move(name), strict }; } - auto exists = environment->has_binding(name); + + Optional index; + auto exists = environment->has_binding(name, &index); if (exception()) return {}; if (exists) - return Reference { *environment, move(name), strict }; + return Reference { *environment, move(name), strict, index }; else return get_identifier_reference(environment->outer_environment(), move(name), strict); }