From 0cd65b55bdd91d5553f5299a7ac5514f86040c15 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 24 Jun 2021 13:24:44 +0200 Subject: LibJS: Add ObjectEnvironmentRecord.[[IsWithEnvironment]] field This is true for environments created by `with` statements, and false for other (global) object environments. Also add the WithBaseObject abstract operation while we're here. --- Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp | 5 +---- Userland/Libraries/LibJS/Runtime/EnvironmentRecord.h | 2 ++ .../Libraries/LibJS/Runtime/GlobalEnvironmentRecord.cpp | 2 +- .../Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp | 3 ++- .../Libraries/LibJS/Runtime/ObjectEnvironmentRecord.h | 17 ++++++++++++++++- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 1865212e0a..082a35e2ea 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -175,10 +175,7 @@ DeclarativeEnvironmentRecord* new_declarative_environment(EnvironmentRecord& env ObjectEnvironmentRecord* new_object_environment(Object& object, bool is_with_environment, EnvironmentRecord* environment_record) { auto& global_object = object.global_object(); - if (!is_with_environment) { - TODO(); - } - return global_object.heap().allocate(global_object, object, environment_record); + return global_object.heap().allocate(global_object, object, is_with_environment ? ObjectEnvironmentRecord::IsWithEnvironment::Yes : ObjectEnvironmentRecord::IsWithEnvironment::No, environment_record); } // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment diff --git a/Userland/Libraries/LibJS/Runtime/EnvironmentRecord.h b/Userland/Libraries/LibJS/Runtime/EnvironmentRecord.h index f4a13278b8..443165818a 100644 --- a/Userland/Libraries/LibJS/Runtime/EnvironmentRecord.h +++ b/Userland/Libraries/LibJS/Runtime/EnvironmentRecord.h @@ -34,6 +34,8 @@ public: virtual bool has_this_binding() const { return false; } virtual Value get_this_binding(GlobalObject&) const { return {}; } + virtual Object* with_base_object() const { return nullptr; } + virtual bool has_binding([[maybe_unused]] FlyString const& name) const { return false; } virtual void create_mutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool can_be_deleted) { } virtual void create_immutable_binding(GlobalObject&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { } diff --git a/Userland/Libraries/LibJS/Runtime/GlobalEnvironmentRecord.cpp b/Userland/Libraries/LibJS/Runtime/GlobalEnvironmentRecord.cpp index ee866636e1..d233052aaf 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalEnvironmentRecord.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalEnvironmentRecord.cpp @@ -16,7 +16,7 @@ GlobalEnvironmentRecord::GlobalEnvironmentRecord(GlobalObject& global_object) : EnvironmentRecord(nullptr) , m_global_object(global_object) { - m_object_record = global_object.heap().allocate(global_object, global_object, nullptr); + m_object_record = global_object.heap().allocate(global_object, global_object, ObjectEnvironmentRecord::IsWithEnvironment::No, nullptr); m_declarative_record = global_object.heap().allocate(global_object); } diff --git a/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp b/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp index 2be830ea7b..b961d97c0a 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp @@ -10,9 +10,10 @@ namespace JS { -ObjectEnvironmentRecord::ObjectEnvironmentRecord(Object& object, EnvironmentRecord* parent_scope) +ObjectEnvironmentRecord::ObjectEnvironmentRecord(Object& object, IsWithEnvironment is_with_environment, EnvironmentRecord* parent_scope) : EnvironmentRecord(parent_scope) , m_object(object) + , m_with_environment(is_with_environment == IsWithEnvironment::Yes) { } diff --git a/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.h b/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.h index f9780f0fb5..707a9ee64b 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.h +++ b/Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.h @@ -14,7 +14,11 @@ class ObjectEnvironmentRecord : public EnvironmentRecord { JS_ENVIRONMENT_RECORD(ObjectEnvironmentRecord, EnvironmentRecord); public: - ObjectEnvironmentRecord(Object&, EnvironmentRecord* parent_scope); + enum class IsWithEnvironment { + No, + Yes, + }; + ObjectEnvironmentRecord(Object&, IsWithEnvironment, EnvironmentRecord* parent_scope); virtual Optional get_from_environment_record(FlyString const&) const override; virtual void put_into_environment_record(FlyString const&, Variable) override; @@ -28,12 +32,23 @@ public: virtual Value get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual bool delete_binding(GlobalObject&, FlyString const& name) override; + // 9.1.1.2.10 WithBaseObject ( ), https://tc39.es/ecma262/#sec-object-environment-records-withbaseobject + virtual Object* with_base_object() const override + { + if (is_with_environment()) + return &m_object; + return nullptr; + } + + bool is_with_environment() const { return m_with_environment; } + Object& object() { return m_object; } private: virtual void visit_edges(Visitor&) override; Object& m_object; + bool m_with_environment { false }; }; } -- cgit v1.2.3