Browse Source

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.
Andreas Kling 4 năm trước cách đây
mục cha
commit
0cd65b55bd

+ 1 - 4
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<ObjectEnvironmentRecord>(global_object, object, environment_record);
+    return global_object.heap().allocate<ObjectEnvironmentRecord>(global_object, object, is_with_environment ? ObjectEnvironmentRecord::IsWithEnvironment::Yes : ObjectEnvironmentRecord::IsWithEnvironment::No, environment_record);
 }
 
 // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment

+ 2 - 0
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) { }

+ 1 - 1
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<ObjectEnvironmentRecord>(global_object, global_object, nullptr);
+    m_object_record = global_object.heap().allocate<ObjectEnvironmentRecord>(global_object, global_object, ObjectEnvironmentRecord::IsWithEnvironment::No, nullptr);
     m_declarative_record = global_object.heap().allocate<DeclarativeEnvironmentRecord>(global_object);
 }
 

+ 2 - 1
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)
 {
 }
 

+ 16 - 1
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<Variable> 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 };
 };
 
 }