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.
This commit is contained in:
Andreas Kling 2021-06-24 13:24:44 +02:00
parent 3f8857cd21
commit 0cd65b55bd
Notes: sideshowbarker 2024-07-18 11:35:23 +09:00
5 changed files with 22 additions and 7 deletions

View file

@ -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

View file

@ -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) { }

View file

@ -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);
}

View file

@ -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)
{
}

View file

@ -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 };
};
}