2022-08-27 13:53:31 +02:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2022 , Andreas Kling < andreas @ ladybird . org >
2022-08-27 13:53:31 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
2022-08-28 13:42:07 +02:00
# include <AK/Weakable.h>
2022-08-27 13:53:31 +02:00
# include <LibJS/Runtime/Object.h>
2025-07-19 19:35:33 -07:00
# include <LibWeb/Export.h>
2022-08-28 13:42:07 +02:00
# include <LibWeb/Forward.h>
2022-08-27 13:53:31 +02:00
namespace Web : : Bindings {
2023-12-24 15:48:00 +13:00
# define WEB_PLATFORM_OBJECT(class_, base_class) \
JS_OBJECT ( class_ , base_class ) \
virtual bool implements_interface ( String const & interface ) const override \
{ \
if ( interface = = # class_ ) \
return true ; \
return Base : : implements_interface ( interface ) ; \
2022-11-29 20:45:35 +01:00
}
2022-08-28 13:42:07 +02:00
2022-08-27 13:53:31 +02:00
// https://webidl.spec.whatwg.org/#dfn-platform-object
2025-07-19 19:35:33 -07:00
class WEB_API PlatformObject : public JS : : Object {
2022-08-27 13:53:31 +02:00
JS_OBJECT ( PlatformObject , JS : : Object ) ;
public :
virtual ~ PlatformObject ( ) override ;
2022-08-28 13:42:07 +02:00
JS : : Realm & realm ( ) const ;
2022-11-29 20:45:35 +01:00
// https://webidl.spec.whatwg.org/#implements
// This is implemented by overrides that get generated by the WEB_PLATFORM_OBJECT macro.
2023-12-24 15:48:00 +13:00
[ [ nodiscard ] ] virtual bool implements_interface ( String const & ) const { return false ; }
2022-11-29 20:45:35 +01:00
2024-01-09 16:05:03 -07:00
// ^JS::Object
virtual JS : : ThrowCompletionOr < Optional < JS : : PropertyDescriptor > > internal_get_own_property ( JS : : PropertyKey const & ) const override ;
2025-09-15 17:23:39 +02:00
virtual JS : : ThrowCompletionOr < bool > internal_set ( JS : : PropertyKey const & , JS : : Value , JS : : Value , JS : : CacheableSetPropertyMetadata * = nullptr , PropertyLookupPhase = PropertyLookupPhase : : OwnProperty ) override ;
2025-09-15 16:43:27 +02:00
virtual JS : : ThrowCompletionOr < bool > internal_define_own_property ( JS : : PropertyKey const & , JS : : PropertyDescriptor & , Optional < JS : : PropertyDescriptor > * precomputed_get_own_property = nullptr ) override ;
2024-01-09 16:05:03 -07:00
virtual JS : : ThrowCompletionOr < bool > internal_delete ( JS : : PropertyKey const & ) override ;
virtual JS : : ThrowCompletionOr < bool > internal_prevent_extensions ( ) override ;
2025-05-16 04:14:12 +01:00
virtual JS : : ThrowCompletionOr < GC : : RootVector < JS : : Value > > internal_own_property_keys ( ) const override ;
2024-01-09 16:05:03 -07:00
JS : : ThrowCompletionOr < bool > is_named_property_exposed_on_object ( JS : : PropertyKey const & ) const ;
2022-08-27 13:53:31 +02:00
protected :
2023-11-09 07:29:52 +00:00
explicit PlatformObject ( JS : : Realm & , MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess : : No ) ;
explicit PlatformObject ( JS : : Object & prototype , MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess : : No ) ;
2024-01-09 16:05:03 -07:00
struct LegacyPlatformObjectFlags {
2025-04-04 07:04:10 -06:00
u16 supports_indexed_properties : 1 = false ;
u16 supports_named_properties : 1 = false ;
u16 has_indexed_property_setter : 1 = false ;
u16 has_named_property_setter : 1 = false ;
u16 has_named_property_deleter : 1 = false ;
u16 has_legacy_unenumerable_named_properties_interface_extended_attribute : 1 = false ;
u16 has_legacy_override_built_ins_interface_extended_attribute : 1 = false ;
u16 has_global_interface_extended_attribute : 1 = false ;
u16 indexed_property_setter_has_identifier : 1 = false ;
u16 named_property_setter_has_identifier : 1 = false ;
u16 named_property_deleter_has_identifier : 1 = false ;
2024-01-09 16:05:03 -07:00
} ;
Optional < LegacyPlatformObjectFlags > m_legacy_platform_object_flags = { } ;
enum class IgnoreNamedProps {
No ,
Yes ,
} ;
JS : : ThrowCompletionOr < Optional < JS : : PropertyDescriptor > > legacy_platform_object_get_own_property ( JS : : PropertyKey const & , IgnoreNamedProps ignore_named_props ) const ;
2024-07-25 18:15:51 +12:00
virtual Optional < JS : : Value > item_value ( size_t index ) const ;
2024-07-25 17:36:10 +12:00
virtual JS : : Value named_item_value ( FlyString const & name ) const ;
2024-01-09 16:05:03 -07:00
virtual Vector < FlyString > supported_property_names ( ) const ;
2024-07-25 07:49:41 +02:00
virtual bool is_supported_property_name ( FlyString const & ) const ;
2024-07-25 18:30:29 +12:00
bool is_supported_property_index ( u32 ) const ;
2024-01-09 16:05:03 -07:00
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
// NOTE: This is only used if named_property_setter_has_identifier returns false, otherwise set_value_of_named_property is used instead.
virtual WebIDL : : ExceptionOr < void > set_value_of_new_named_property ( String const & , JS : : Value ) ;
virtual WebIDL : : ExceptionOr < void > set_value_of_existing_named_property ( String const & , JS : : Value ) ;
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
// NOTE: This is only used if you make named_property_setter_has_identifier return true, otherwise set_value_of_{new,existing}_named_property is used instead.
virtual WebIDL : : ExceptionOr < void > set_value_of_named_property ( String const & , JS : : Value ) ;
// NOTE: These will crash if you make has_indexed_property_setter return true but do not override these methods.
// NOTE: This is only used if indexed_property_setter_has_identifier returns false, otherwise set_value_of_indexed_property is used instead.
virtual WebIDL : : ExceptionOr < void > set_value_of_new_indexed_property ( u32 , JS : : Value ) ;
virtual WebIDL : : ExceptionOr < void > set_value_of_existing_indexed_property ( u32 , JS : : Value ) ;
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
// NOTE: This is only used if indexed_property_setter_has_identifier returns true, otherwise set_value_of_{new,existing}_indexed_property is used instead.
virtual WebIDL : : ExceptionOr < void > set_value_of_indexed_property ( u32 , JS : : Value ) ;
enum class DidDeletionFail {
// If the named property deleter has an identifier, but does not return a boolean.
// This is done because we don't know the return type of the deleter outside of the IDL generator.
NotRelevant ,
No ,
Yes ,
} ;
// NOTE: This will crash if you make has_named_property_deleter return true but do not override this method.
virtual WebIDL : : ExceptionOr < DidDeletionFail > delete_value ( String const & ) ;
LibJS: Fast-path own-property enumeration and reduce descriptor lookups
Before this change, PropertyNameIterator (used by for..in) and
`Object::enumerable_own_property_names()` (used by `Object.keys()`,
`Object.values()`, and `Object.entries()`) enumerated an object's own
enumerable properties exactly as the spec prescribes:
- Call `internal_own_property_keys()`, allocating a list of JS::Value
keys.
- For each key, call internal_get_own_property() to obtain a
descriptor and check `[[Enumerable]]`.
While that is required in the general case (e.g. for Proxy objects or
platform/exotic objects that override `[[OwnPropertyKeys]]`), it's
overkill for ordinary JS objects that store their own properties in the
shape table and indexed-properties storage.
This change introduces `for_each_own_property_with_enumerability()`,
which, for objects where
`eligible_for_own_property_enumeration_fast_path()` is `true`, lets us
read the enumerability directly from shape metadata (and from
indexed-properties storage) without a per-property descriptor lookup.
When we cannot avoid `internal_get_own_property()`, we still
benefit by skipping the temporary `Vector<Value>` of keys and avoiding
the unnecessary round-trip between PropertyKey and Value.
2025-09-19 16:49:53 +02:00
virtual bool eligible_for_own_property_enumeration_fast_path ( ) const override final { return false ; }
2024-01-09 16:05:03 -07:00
private :
WebIDL : : ExceptionOr < void > invoke_indexed_property_setter ( JS : : PropertyKey const & , JS : : Value ) ;
2024-07-25 19:02:35 +12:00
WebIDL : : ExceptionOr < void > invoke_named_property_setter ( FlyString const & , JS : : Value ) ;
2022-08-27 13:53:31 +02:00
} ;
}