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