From 540ce075b6e904f0926cca1592cff998a9f6e407 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 7 Oct 2021 00:10:00 +0200 Subject: [PATCH] LibJS: Add direct (indexed) binding accessors to DeclarativeEnvironment This patch adds two DeclarativeEnvironment APIs: - get_binding_value_direct() - set_mutable_binding_direct() These work identically to their non-direct-suffixed counterparts, but take an index instead of a bound name. This will allow someone who has a binding index to get/set that binding directly without any additional hash lookups. --- .../LibJS/Runtime/DeclarativeEnvironment.cpp | 29 +++++++++++++++---- .../LibJS/Runtime/DeclarativeEnvironment.h | 5 ++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp index df05c978a3..3514143757 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp @@ -98,12 +98,17 @@ void DeclarativeEnvironment::set_mutable_binding(GlobalObject& global_object, Fl return; } - auto& binding = m_bindings[it->value]; + set_mutable_binding_direct(global_object, it->value, value, strict); +} + +void DeclarativeEnvironment::set_mutable_binding_direct(GlobalObject& global_object, size_t index, Value value, bool strict) +{ + auto& binding = m_bindings[index]; if (binding.strict) strict = true; if (!binding.initialized) { - global_object.vm().throw_exception(global_object, ErrorType::BindingNotInitialized, name); + global_object.vm().throw_exception(global_object, ErrorType::BindingNotInitialized, name_from_index(index)); return; } @@ -117,13 +122,18 @@ void DeclarativeEnvironment::set_mutable_binding(GlobalObject& global_object, Fl } // 9.1.1.1.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-getbindingvalue-n-s -Value DeclarativeEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool) +Value DeclarativeEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict) { auto it = m_names.find(name); VERIFY(it != m_names.end()); - auto& binding = m_bindings[it->value]; + return get_binding_value_direct(global_object, it->value, strict); +} + +Value DeclarativeEnvironment::get_binding_value_direct(GlobalObject& global_object, size_t index, bool) +{ + auto& binding = m_bindings[index]; if (!binding.initialized) { - global_object.vm().throw_exception(global_object, ErrorType::BindingNotInitialized, name); + global_object.vm().throw_exception(global_object, ErrorType::BindingNotInitialized, name_from_index(index)); return {}; } return binding.value; @@ -163,4 +173,13 @@ Vector DeclarativeEnvironment::bindings() const return names; } +FlyString const& DeclarativeEnvironment::name_from_index(size_t index) const +{ + for (auto& it : m_names) { + if (it.value == index) + return it.key; + } + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h index 283346f50a..16993e5c49 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h @@ -34,10 +34,15 @@ public: // This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code. [[nodiscard]] Vector bindings() const; + Value get_binding_value_direct(GlobalObject&, size_t index, bool strict); + void set_mutable_binding_direct(GlobalObject&, size_t index, Value, bool strict); + protected: virtual void visit_edges(Visitor&) override; private: + FlyString const& name_from_index(size_t) const; + virtual bool is_declarative_environment() const override { return true; } struct Binding {