2021-10-02 20:33:45 +01:00
/*
* Copyright ( c ) 2021 , Luke Wilde < lukew @ serenityos . org >
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2022 , Andreas Kling < andreas @ ladybird . org >
2021-10-02 20:33:45 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2024-11-15 04:01:23 +13:00
# include <LibGC/Heap.h>
2023-07-09 11:40:17 +03:30
# include <LibJS/Runtime/Error.h>
2021-10-02 20:33:45 +01:00
# include <LibWeb/DOM/LiveNodeList.h>
# include <LibWeb/DOM/Node.h>
namespace Web : : DOM {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( LiveNodeList ) ;
2023-11-19 19:47:52 +01:00
2024-11-15 04:01:23 +13:00
GC : : Ref < NodeList > LiveNodeList : : create ( JS : : Realm & realm , Node const & root , Scope scope , Function < bool ( Node const & ) > filter )
2022-09-01 16:30:26 +02:00
{
2024-11-14 05:50:17 +13:00
return realm . create < LiveNodeList > ( realm , root , scope , move ( filter ) ) ;
2022-09-01 16:30:26 +02:00
}
2023-12-21 22:36:37 +13:00
LiveNodeList : : LiveNodeList ( JS : : Realm & realm , Node const & root , Scope scope , Function < bool ( Node const & ) > filter )
2022-09-25 16:15:49 -06:00
: NodeList ( realm )
2022-09-01 16:30:26 +02:00
, m_root ( root )
2021-10-02 20:33:45 +01:00
, m_filter ( move ( filter ) )
2023-05-23 12:28:16 +02:00
, m_scope ( scope )
2021-10-02 20:33:45 +01:00
{
}
2022-09-01 16:30:26 +02:00
LiveNodeList : : ~ LiveNodeList ( ) = default ;
void LiveNodeList : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2023-11-19 16:18:00 +13:00
visitor . visit ( m_root ) ;
2022-09-01 16:30:26 +02:00
}
2024-12-26 14:32:52 +01:00
GC : : RootVector < Node * > LiveNodeList : : collection ( ) const
2021-10-02 20:33:45 +01:00
{
2024-12-26 14:32:52 +01:00
GC : : RootVector < Node * > nodes ( heap ( ) ) ;
2023-05-23 12:28:16 +02:00
if ( m_scope = = Scope : : Descendants ) {
m_root - > for_each_in_subtree ( [ & ] ( auto & node ) {
if ( m_filter ( node ) )
nodes . append ( const_cast < Node * > ( & node ) ) ;
2024-05-04 14:47:04 +01:00
return TraversalDecision : : Continue ;
2023-05-23 12:28:16 +02:00
} ) ;
} else {
m_root - > for_each_child ( [ & ] ( auto & node ) {
if ( m_filter ( node ) )
nodes . append ( const_cast < Node * > ( & node ) ) ;
return IterationDecision : : Continue ;
} ) ;
}
2021-10-02 20:33:45 +01:00
return nodes ;
}
2023-08-25 12:16:44 +12:00
Node * LiveNodeList : : first_matching ( Function < bool ( Node const & ) > const & filter ) const
{
Node * matched_node = nullptr ;
if ( m_scope = = Scope : : Descendants ) {
m_root - > for_each_in_subtree ( [ & ] ( auto & node ) {
if ( m_filter ( node ) & & filter ( node ) ) {
matched_node = const_cast < Node * > ( & node ) ;
2024-05-04 14:47:04 +01:00
return TraversalDecision : : Break ;
2023-08-25 12:16:44 +12:00
}
2024-05-04 14:47:04 +01:00
return TraversalDecision : : Continue ;
2023-08-25 12:16:44 +12:00
} ) ;
} else {
m_root - > for_each_child ( [ & ] ( auto & node ) {
if ( m_filter ( node ) & & filter ( node ) ) {
matched_node = const_cast < Node * > ( & node ) ;
return IterationDecision : : Break ;
}
return IterationDecision : : Continue ;
} ) ;
}
return matched_node ;
}
2021-10-02 20:33:45 +01:00
// https://dom.spec.whatwg.org/#dom-nodelist-length
u32 LiveNodeList : : length ( ) const
{
return collection ( ) . size ( ) ;
}
// https://dom.spec.whatwg.org/#dom-nodelist-item
Node const * LiveNodeList : : item ( u32 index ) const
{
// The item(index) method must return the indexth node in the collection. If there is no indexth node in the collection, then the method must return null.
auto nodes = collection ( ) ;
if ( index > = nodes . size ( ) )
return nullptr ;
2022-08-28 13:42:07 +02:00
return nodes [ index ] ;
2021-10-02 20:33:45 +01:00
}
}