2021-10-15 09:57:07 -04:00
/*
2022-01-31 13:07:22 -05:00
* Copyright ( c ) 2021 , Tim Flynn < trflynn89 @ serenityos . org >
2023-03-29 23:46:18 +01:00
* Copyright ( c ) 2023 , Luke Wilde < lukew @ serenityos . org >
2021-10-15 09:57:07 -04:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-09-25 16:15:49 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2022-09-18 01:03:58 +02:00
# include <LibWeb/DOM/Attr.h>
2021-10-15 09:57:07 -04:00
# include <LibWeb/DOM/Document.h>
2021-10-17 15:09:47 -04:00
# include <LibWeb/DOM/Element.h>
2022-07-11 16:40:01 +01:00
# include <LibWeb/DOM/MutationType.h>
# include <LibWeb/DOM/StaticNodeList.h>
2023-03-29 23:46:18 +01:00
# include <LibWeb/HTML/CustomElements/CustomElementReactionNames.h>
2021-10-15 09:57:07 -04:00
namespace Web : : DOM {
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( Attr ) ;
2023-09-10 16:06:58 +12:00
JS : : NonnullGCPtr < Attr > Attr : : create ( Document & document , FlyString local_name , String value , Element * owner_element )
2021-10-15 09:57:07 -04:00
{
2023-09-10 16:06:58 +12:00
return document . heap ( ) . allocate < Attr > ( document . realm ( ) , document , QualifiedName ( move ( local_name ) , Optional < FlyString > { } , Optional < FlyString > { } ) , move ( value ) , owner_element ) ;
2021-10-15 09:57:07 -04:00
}
2023-09-10 16:06:58 +12:00
JS : : NonnullGCPtr < Attr > Attr : : create ( Document & document , QualifiedName qualified_name , String value , Element * owner_element )
2023-03-10 14:56:29 +01:00
{
2023-08-13 13:05:26 +02:00
return document . heap ( ) . allocate < Attr > ( document . realm ( ) , document , move ( qualified_name ) , move ( value ) , owner_element ) ;
2023-03-10 14:56:29 +01:00
}
2022-12-13 13:08:46 +01:00
JS : : NonnullGCPtr < Attr > Attr : : clone ( Document & document )
{
2023-08-13 13:05:26 +02:00
return * heap ( ) . allocate < Attr > ( realm ( ) , document , m_qualified_name , m_value , nullptr ) ;
2022-12-13 13:08:46 +01:00
}
2023-09-10 16:06:58 +12:00
Attr : : Attr ( Document & document , QualifiedName qualified_name , String value , Element * owner_element )
2021-10-15 09:57:07 -04:00
: Node ( document , NodeType : : ATTRIBUTE_NODE )
2022-12-13 13:08:46 +01:00
, m_qualified_name ( move ( qualified_name ) )
2024-03-15 18:19:59 +01:00
, m_lowercase_name ( MUST ( String ( m_qualified_name . as_string ( ) ) . to_lowercase ( ) ) )
2021-10-15 09:57:07 -04:00
, m_value ( move ( value ) )
2021-10-15 12:03:08 -04:00
, m_owner_element ( owner_element )
2021-10-15 09:57:07 -04:00
{
2023-01-10 06:28:20 -05:00
}
2023-08-07 08:41:28 +02:00
void Attr : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2023-11-22 12:55:21 +13:00
set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : AttrPrototype > ( realm , " Attr " _fly_string ) ) ;
2022-08-28 13:42:07 +02:00
}
2022-09-18 01:03:58 +02:00
void Attr : : visit_edges ( Cell : : Visitor & visitor )
2022-08-28 13:42:07 +02:00
{
Base : : visit_edges ( visitor ) ;
2023-11-19 16:18:00 +13:00
visitor . visit ( m_owner_element ) ;
2021-10-15 09:57:07 -04:00
}
2023-03-29 23:46:18 +01:00
Element * Attr : : owner_element ( )
{
return m_owner_element . ptr ( ) ;
}
2022-09-18 01:03:58 +02:00
Element const * Attr : : owner_element ( ) const
2021-10-17 15:09:47 -04:00
{
2022-08-28 13:42:07 +02:00
return m_owner_element . ptr ( ) ;
2021-10-17 15:09:47 -04:00
}
2023-03-29 23:46:18 +01:00
void Attr : : set_owner_element ( Element * owner_element )
2021-10-17 15:09:47 -04:00
{
m_owner_element = owner_element ;
}
2022-07-11 16:40:01 +01:00
// https://dom.spec.whatwg.org/#set-an-existing-attribute-value
2023-09-10 16:06:58 +12:00
void Attr : : set_value ( String value )
2022-07-11 16:40:01 +01:00
{
// 1. If attribute’ s element is null, then set attribute’ s value to value.
if ( ! owner_element ( ) ) {
m_value = move ( value ) ;
}
// 2. Otherwise, change attribute to value.
2023-09-01 10:40:37 -04:00
else {
change_attribute ( move ( value ) ) ;
}
}
// https://dom.spec.whatwg.org/#concept-element-attributes-change
2023-09-10 16:06:58 +12:00
void Attr : : change_attribute ( String value )
2023-09-01 10:40:37 -04:00
{
// 1. Let oldValue be attribute’ s value.
auto old_value = move ( m_value ) ;
2022-07-11 16:40:01 +01:00
// 2. Set attribute’ s value to value.
m_value = move ( value ) ;
2023-09-01 10:40:37 -04:00
// 3. Handle attribute changes for attribute with attribute’ s element, oldValue, and value.
2023-11-19 18:10:36 +13:00
handle_attribute_changes ( * owner_element ( ) , old_value , m_value ) ;
2022-07-11 16:40:01 +01:00
}
// https://dom.spec.whatwg.org/#handle-attribute-changes
2023-11-19 18:10:36 +13:00
void Attr : : handle_attribute_changes ( Element & element , Optional < String > const & old_value , Optional < String > const & new_value )
2022-07-11 16:40:01 +01:00
{
// 1. Queue a mutation record of "attributes" for element with attribute’ s local name, attribute’ s namespace, oldValue, « », « », null, and null.
2023-11-19 18:10:36 +13:00
element . queue_mutation_record ( MutationType : : attributes , local_name ( ) , namespace_uri ( ) , old_value , { } , { } , nullptr , nullptr ) ;
2022-07-11 16:40:01 +01:00
2023-03-29 23:46:18 +01:00
// 2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attribute’ s local name, oldValue, newValue, and attribute’ s namespace.
if ( element . is_custom ( ) ) {
auto & vm = this - > vm ( ) ;
JS : : MarkedVector < JS : : Value > arguments { vm . heap ( ) } ;
arguments . append ( JS : : PrimitiveString : : create ( vm , local_name ( ) ) ) ;
2023-11-19 18:10:36 +13:00
arguments . append ( ! old_value . has_value ( ) ? JS : : js_null ( ) : JS : : PrimitiveString : : create ( vm , old_value . value ( ) ) ) ;
arguments . append ( ! new_value . has_value ( ) ? JS : : js_null ( ) : JS : : PrimitiveString : : create ( vm , new_value . value ( ) ) ) ;
2023-09-10 16:06:58 +12:00
arguments . append ( ! namespace_uri ( ) . has_value ( ) ? JS : : js_null ( ) : JS : : PrimitiveString : : create ( vm , namespace_uri ( ) . value ( ) ) ) ;
2023-03-29 23:46:18 +01:00
element . enqueue_a_custom_element_callback_reaction ( HTML : : CustomElementReactionNames : : attributeChangedCallback , move ( arguments ) ) ;
}
2022-07-11 16:40:01 +01:00
2023-09-02 10:05:15 -04:00
// 3. Run the attribute change steps with element, attribute’ s local name, oldValue, newValue, and attribute’ s namespace.
2023-11-07 08:07:02 +13:00
element . run_attribute_change_steps ( local_name ( ) , old_value , new_value , namespace_uri ( ) ) ;
2022-07-11 16:40:01 +01:00
}
2021-10-15 09:57:07 -04:00
}