/* * Copyright (c) 2021, Luke Wilde * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include namespace Web::DOM { GC_DEFINE_ALLOCATOR(LiveNodeList); GC::Ref LiveNodeList::create(JS::Realm& realm, Node const& root, Scope scope, Function filter) { return realm.create(realm, root, scope, move(filter)); } LiveNodeList::LiveNodeList(JS::Realm& realm, Node const& root, Scope scope, Function filter) : NodeList(realm) , m_root(root) , m_filter(move(filter)) , m_scope(scope) { } LiveNodeList::~LiveNodeList() = default; void LiveNodeList::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_root); } GC::RootVector LiveNodeList::collection() const { GC::RootVector nodes(heap()); if (m_scope == Scope::Descendants) { m_root->for_each_in_subtree([&](auto& node) { if (m_filter(node)) nodes.append(const_cast(&node)); return TraversalDecision::Continue; }); } else { m_root->for_each_child([&](auto& node) { if (m_filter(node)) nodes.append(const_cast(&node)); return IterationDecision::Continue; }); } return nodes; } Node* LiveNodeList::first_matching(Function 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); return TraversalDecision::Break; } return TraversalDecision::Continue; }); } else { m_root->for_each_child([&](auto& node) { if (m_filter(node) && filter(node)) { matched_node = const_cast(&node); return IterationDecision::Break; } return IterationDecision::Continue; }); } return matched_node; } // 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; return nodes[index]; } }