1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 00:27:43 +00:00

LibJS: Distinguish between omitted descriptor attributes and false ones

When calling Object.defineProperty, there is now a difference between
omitting a descriptor attribute and specifying that it is false. For
example, "{}" and "{ configurable: false }" will have different
attribute values.
This commit is contained in:
Matthew Olsson 2020-06-02 17:13:09 -07:00 committed by Andreas Kling
parent 5c485d4a1e
commit 5ad5322f6a
8 changed files with 186 additions and 83 deletions

View file

@ -31,35 +31,23 @@
#include <AK/OwnPtr.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/Cell.h>
#include <LibJS/Runtime/PropertyAttributes.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
struct Attribute {
enum {
Configurable = 1 << 0,
Enumerable = 1 << 1,
Writable = 1 << 2,
HasGet = 1 << 3,
HasSet = 1 << 4,
};
};
const u8 default_attributes = Attribute::Configurable | Attribute::Writable | Attribute::Enumerable;
struct PropertyMetadata {
size_t offset { 0 };
u8 attributes { 0 };
PropertyAttributes attributes { 0 };
};
struct TransitionKey {
FlyString property_name;
u8 attributes { 0 };
PropertyAttributes attributes { 0 };
bool operator==(const TransitionKey& other) const
{
return property_name == other.property_name
&& attributes == other.attributes;
return property_name == other.property_name && attributes == other.attributes;
}
};
@ -75,11 +63,11 @@ public:
};
Shape();
Shape(Shape* previous_shape, const FlyString& property_name, u8 attributes, TransitionType);
Shape(Shape* previous_shape, const FlyString& property_name, PropertyAttributes attributes, TransitionType);
Shape(Shape* previous_shape, Object* new_prototype);
Shape* create_put_transition(const FlyString& name, u8 attributes);
Shape* create_configure_transition(const FlyString& name, u8 attributes);
Shape* create_put_transition(const FlyString& name, PropertyAttributes attributes);
Shape* create_configure_transition(const FlyString& name, PropertyAttributes attributes);
Shape* create_prototype_transition(Object* new_prototype);
bool is_unique() const { return m_unique; }
@ -102,8 +90,8 @@ public:
void set_prototype_without_transition(Object* new_prototype) { m_prototype = new_prototype; }
void remove_property_from_unique_shape(const FlyString&, size_t offset);
void add_property_to_unique_shape(const FlyString&, u8 attributes);
void reconfigure_property_in_unique_shape(const FlyString& property_name, u8 attributes);
void add_property_to_unique_shape(const FlyString&, PropertyAttributes attributes);
void reconfigure_property_in_unique_shape(const FlyString& property_name, PropertyAttributes attributes);
private:
virtual const char* class_name() const override { return "Shape"; }
@ -116,7 +104,7 @@ private:
HashMap<TransitionKey, Shape*> m_forward_transitions;
Shape* m_previous { nullptr };
FlyString m_property_name;
u8 m_attributes { 0 };
PropertyAttributes m_attributes { 0 };
bool m_unique { false };
Object* m_prototype { nullptr };
TransitionType m_transition_type { TransitionType::Invalid };
@ -128,6 +116,6 @@ template<>
struct AK::Traits<JS::TransitionKey> : public GenericTraits<JS::TransitionKey> {
static unsigned hash(const JS::TransitionKey& key)
{
return pair_int_hash(int_hash(key.attributes), key.property_name.hash());
return pair_int_hash(key.attributes.bits(), key.property_name.hash());
}
};