rdom/
node_list.rs

1//! Representation of a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
2//! and associated metadata.
3
4use crate::internal_prelude::*;
5
6crate::use_behaviors!(sandbox_member);
7
8/// Represents a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) structure,
9/// which may be either "live" or "static". Note that these are not strongly retained by the
10/// Sandbox, and there is no guarantee they will work after the Sandbox has been dropped. So, to
11/// use a NodeList, make sure you have retained both the Sandbox and an Rc to the NodeList before
12/// performing any operations.
13///
14/// Also note that retaining a NodeList may cause other Nodes to be retained. For example,
15/// `some_node.child_nodes()` and retaining the return value will cause `some_node` to be
16/// retained.
17pub struct NodeList {
18    /// Reference to the sandbox to which this NodeList belongs
19    pub context: SandboxMemberBehaviorStorage,
20
21    /// The underlying storage
22    pub(crate) nodelist_storage: NodeListStorage,
23}
24
25impl NodeList {
26    pub(crate) fn new(context: Weak<Sandbox>, nodelist_storage: NodeListStorage) -> Arc<NodeList> {
27        Arc::new(NodeList {
28            context: SandboxMemberBehaviorStorage::new(context),
29            nodelist_storage,
30        })
31    }
32
33    pub(crate) fn new_static(context: Weak<Sandbox>, elements: Vec<AnyNodeArc>) -> Arc<NodeList> {
34        let nodelist_storage = NodeListStorage::Static(elements);
35        NodeList::new(context, nodelist_storage)
36    }
37
38    /// NodeList#length
39    pub fn length(&self) -> usize {
40        match &self.nodelist_storage {
41            NodeListStorage::Static(list) => list.len(),
42            NodeListStorage::Live(query) => match query {
43                Query::ChildNodes { children_of } => {
44                    children_of.common.node_graph.static_child_nodes().len()
45                }
46            },
47        }
48    }
49
50    /// NodeList#item
51    pub fn item(&self, index: usize) -> Option<AnyNodeArc> {
52        match &self.nodelist_storage {
53            NodeListStorage::Static(list) => list.get(index).cloned(),
54            NodeListStorage::Live(query) => match query {
55                Query::ChildNodes { children_of } => children_of
56                    .common
57                    .node_graph
58                    .static_child_nodes()
59                    .get(index)
60                    .cloned(),
61            },
62        }
63    }
64
65    /// NodeList#get
66    pub fn get(&self, index: usize) -> Option<AnyNodeArc> {
67        self.item(index)
68    }
69}
70
71impl_sandbox_member!(NodeList, context);
72
73/// An encapsulation of how the NodeList will respond to operations.
74pub(crate) enum NodeListStorage {
75    /// A static list of nodes (e.g. result of Document.query_selector_all(...))
76    Static(Vec<AnyNodeArc>),
77
78    /// Some dynamic query (e.g. result of Node.child_nodes())
79    Live(Query),
80}
81
82pub(crate) enum Query {
83    ChildNodes { children_of: AnyNodeArc },
84}