Skip to content

Commit

Permalink
LibJS: Add the [[Unimplemented]] attribute
Browse files Browse the repository at this point in the history
Properties marked with the [[Unimplemented]] attribute behave as normal
but invoke the `VM::on_unimplemented_property_access callback` when
they are accessed.

(cherry picked from commit 88d425f32b3b49d5dfa8d86e6e4e2c263cd450d4)
  • Loading branch information
tcl3 authored and nico committed Jun 24, 2024
1 parent 0b1adf7 commit e67a8b8
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Userland/Libraries/LibJS/Runtime/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,13 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_propert
// 3. Let X be O's own property whose key is P.
auto [value, attributes, property_offset] = *maybe_storage_entry;

// AD-HOC: Properties with the [[Unimplemented]] attribute are used for reporting unimplemented IDL interfaces.
if (attributes.is_unimplemented()) {
if (vm().on_unimplemented_property_access)
vm().on_unimplemented_property_access(*this, property_key);
descriptor.unimplemented = true;
}

// 4. If X is a data property, then
if (!value.is_accessor()) {
// a. Set D.[[Value]] to the value of X's [[Value]] attribute.
Expand Down
3 changes: 3 additions & 0 deletions Userland/Libraries/LibJS/Runtime/PropertyAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ struct Attribute {
Writable = 1 << 0,
Enumerable = 1 << 1,
Configurable = 1 << 2,
// AD-HOC: This is used for reporting unimplemented IDL interfaces.
Unimplemented = 1 << 3,
};
};

Expand All @@ -33,6 +35,7 @@ class PropertyAttributes {
[[nodiscard]] bool is_writable() const { return m_bits & Attribute::Writable; }
[[nodiscard]] bool is_enumerable() const { return m_bits & Attribute::Enumerable; }
[[nodiscard]] bool is_configurable() const { return m_bits & Attribute::Configurable; }
[[nodiscard]] bool is_unimplemented() const { return m_bits & Attribute::Unimplemented; }

void set_writable(bool writable = true)
{
Expand Down
5 changes: 4 additions & 1 deletion Userland/Libraries/LibJS/Runtime/PropertyDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class PropertyDescriptor {
// Not a standard abstract operation, but "If every field in Desc is absent".
[[nodiscard]] bool is_empty() const
{
return !value.has_value() && !get.has_value() && !set.has_value() && !writable.has_value() && !enumerable.has_value() && !configurable.has_value();
return !value.has_value() && !get.has_value() && !set.has_value() && !writable.has_value() && !enumerable.has_value() && !configurable.has_value() && !unimplemented.has_value();
}

Optional<Value> value {};
Expand All @@ -40,6 +40,7 @@ class PropertyDescriptor {
Optional<bool> writable {};
Optional<bool> enumerable {};
Optional<bool> configurable {};
Optional<bool> unimplemented {};

Optional<u32> property_offset {};
};
Expand All @@ -65,6 +66,8 @@ struct Formatter<JS::PropertyDescriptor> : Formatter<StringView> {
TRY(parts.try_append(TRY(String::formatted("[[Enumerable]]: {}", *property_descriptor.enumerable))));
if (property_descriptor.configurable.has_value())
TRY(parts.try_append(TRY(String::formatted("[[Configurable]]: {}", *property_descriptor.configurable))));
if (property_descriptor.unimplemented.has_value())
TRY(parts.try_append(TRY(String::formatted("[[Unimplemented]]: {}", *property_descriptor.unimplemented))));
return Formatter<StringView>::format(builder, TRY(String::formatted("PropertyDescriptor {{ {} }}", TRY(String::join(", "sv, parts)))));
}
};
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibJS/Runtime/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ class VM : public RefCounted<VM> {
Function<void()> on_call_stack_emptied;
Function<void(Promise&)> on_promise_unhandled_rejection;
Function<void(Promise&)> on_promise_rejection_handled;
Function<void(Object const&, PropertyKey const&)> on_unimplemented_property_access;

CustomData* custom_data() { return m_custom_data; }

Expand Down

0 comments on commit e67a8b8

Please sign in to comment.