Skip to main content

script/dom/node/
context.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cell::Cell;
6
7use crate::dom::Node;
8
9/// The context of the binding to tree of a node.
10pub(crate) struct BindContext<'a> {
11    /// The parent of the inclusive ancestor that was inserted.
12    pub(crate) parent: &'a Node,
13
14    /// Whether the tree is connected.
15    ///
16    /// <https://dom.spec.whatwg.org/#connected>
17    pub(crate) tree_connected: bool,
18
19    /// Whether the tree's root is a document.
20    ///
21    /// <https://dom.spec.whatwg.org/#in-a-document-tree>
22    pub(crate) tree_is_in_a_document_tree: bool,
23
24    /// Whether the tree's root is a shadow root
25    pub(crate) tree_is_in_a_shadow_tree: bool,
26
27    /// Whether the root of the subtree that is being bound to the parent is a shadow root.
28    ///
29    /// This implies that all elements whose "bind_to_tree" method are called were already
30    /// in a shadow tree beforehand.
31    pub(crate) is_shadow_tree: IsShadowTree,
32}
33
34#[derive(Debug, Eq, PartialEq)]
35pub(crate) enum IsShadowTree {
36    Yes,
37    No,
38}
39
40impl<'a> BindContext<'a> {
41    /// Create a new `BindContext` value.
42    pub(crate) fn new(parent: &'a Node, is_shadow_tree: IsShadowTree) -> Self {
43        BindContext {
44            parent,
45            tree_connected: parent.is_connected(),
46            tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
47            tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
48            is_shadow_tree,
49        }
50    }
51
52    /// Return true iff the tree is inside either a document- or a shadow tree.
53    pub(crate) fn is_in_tree(&self) -> bool {
54        self.tree_is_in_a_document_tree || self.tree_is_in_a_shadow_tree
55    }
56}
57
58/// The context of the unbinding from a tree of a node when one of its
59/// inclusive ancestors is removed.
60pub(crate) struct UnbindContext<'a> {
61    /// The index of the inclusive ancestor that was removed.
62    index: Cell<Option<u32>>,
63    /// The parent of the inclusive ancestor that was removed.
64    pub(crate) parent: &'a Node,
65    /// The previous sibling of the inclusive ancestor that was removed.
66    prev_sibling: Option<&'a Node>,
67    /// The next sibling of the inclusive ancestor that was removed.
68    pub(crate) next_sibling: Option<&'a Node>,
69
70    /// Whether the tree is connected.
71    ///
72    /// <https://dom.spec.whatwg.org/#connected>
73    pub(crate) tree_connected: bool,
74
75    /// Whether the tree's root is a document.
76    ///
77    /// <https://dom.spec.whatwg.org/#in-a-document-tree>
78    pub(crate) tree_is_in_a_document_tree: bool,
79
80    /// Whether the tree's root is a shadow root
81    pub(crate) tree_is_in_a_shadow_tree: bool,
82}
83
84impl<'a> UnbindContext<'a> {
85    /// Create a new `UnbindContext` value.
86    pub(crate) fn new(
87        parent: &'a Node,
88        prev_sibling: Option<&'a Node>,
89        next_sibling: Option<&'a Node>,
90        cached_index: Option<u32>,
91    ) -> Self {
92        UnbindContext {
93            index: Cell::new(cached_index),
94            parent,
95            prev_sibling,
96            next_sibling,
97            tree_connected: parent.is_connected(),
98            tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
99            tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
100        }
101    }
102
103    /// The index of the inclusive ancestor that was removed from the tree.
104    pub(crate) fn index(&self) -> u32 {
105        if let Some(index) = self.index.get() {
106            return index;
107        }
108        let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
109        self.index.set(Some(index));
110        index
111    }
112}
113
114/// The context of the moving from a tree of a node when one of its
115/// inclusive ancestors is moved.
116pub(crate) struct MoveContext<'a> {
117    /// The index of the inclusive ancestor that was moved.
118    index: Cell<Option<u32>>,
119    /// The old parent, if any, of the inclusive ancestor that was moved.
120    pub(crate) old_parent: Option<&'a Node>,
121    /// The previous sibling of the inclusive ancestor that was moved.
122    prev_sibling: Option<&'a Node>,
123    /// The next sibling of the inclusive ancestor that was moved.
124    pub(crate) next_sibling: Option<&'a Node>,
125}
126
127impl<'a> MoveContext<'a> {
128    /// Create a new `MoveContext` value.
129    pub(crate) fn new(
130        old_parent: Option<&'a Node>,
131        prev_sibling: Option<&'a Node>,
132        next_sibling: Option<&'a Node>,
133        cached_index: Option<u32>,
134    ) -> Self {
135        MoveContext {
136            index: Cell::new(cached_index),
137            old_parent,
138            prev_sibling,
139            next_sibling,
140        }
141    }
142
143    /// The index of the inclusive ancestor that was moved from the tree.
144    pub(crate) fn index(&self) -> u32 {
145        if let Some(index) = self.index.get() {
146            return index;
147        }
148        let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
149        self.index.set(Some(index));
150        index
151    }
152}