1use blitz_traits::node_id::NodeId;
2use selectors::SelectorList;
3use smallvec::SmallVec;
4use style::dom::{TDocument, TNode};
5use style::dom_apis::{
6 MayUseInvalidation, QueryAll, QueryFirst, element_closest, element_matches, query_selector,
7};
8use style::selector_parser::{SelectorImpl, SelectorParser};
9use style_traits::ParseError;
10
11use crate::{BaseDocument, Node};
12
13impl BaseDocument {
14 pub fn get_element_by_id(&self, id: &str) -> Option<NodeId> {
17 match self.nodes_to_id.get(id)?.as_slice() {
18 [] => None,
19 [node_id] => Some(*node_id),
20 candidates => self.first_in_tree_order(candidates),
21 }
22 }
23
24 fn first_in_tree_order(&self, candidates: &[NodeId]) -> Option<NodeId> {
26 let mut stack = vec![self.root_node_id];
27 while let Some(node_id) = stack.pop() {
28 if candidates.contains(&node_id) {
29 return Some(node_id);
30 }
31 stack.extend(self.nodes[node_id].children.iter().rev().copied());
32 }
33 None
34 }
35
36 pub(crate) fn add_to_id_map(&mut self, id: &str, node_id: NodeId) {
38 if id.is_empty() {
39 return;
40 }
41 let node_ids = self.nodes_to_id.entry(id.to_string()).or_default();
42 if !node_ids.contains(&node_id) {
43 node_ids.push(node_id);
44 }
45 }
46
47 pub(crate) fn remove_from_id_map(&mut self, id: &str, node_id: NodeId) {
49 if let Some(node_ids) = self.nodes_to_id.get_mut(id) {
50 node_ids.retain(|nid| *nid != node_id);
51 if node_ids.is_empty() {
52 self.nodes_to_id.remove(id);
53 }
54 }
55 }
56
57 pub fn query_selector<'input>(
63 &self,
64 selector: &'input str,
65 ) -> Result<Option<NodeId>, ParseError<'input>> {
66 self.query_selector_in(self.root_node_id, selector)
67 }
68
69 pub fn query_selector_in<'input>(
80 &self,
81 scope: NodeId,
82 selector: &'input str,
83 ) -> Result<Option<NodeId>, ParseError<'input>> {
84 let selector_list = self.try_parse_selector_list(selector)?;
85 Ok(self.query_selector_in_raw(scope, &selector_list))
86 }
87
88 pub fn query_selector_raw(&self, selector_list: &SelectorList<SelectorImpl>) -> Option<NodeId> {
95 self.query_selector_in_raw(self.root_node_id, selector_list)
96 }
97
98 pub fn query_selector_in_raw(
104 &self,
105 scope: NodeId,
106 selector_list: &SelectorList<SelectorImpl>,
107 ) -> Option<NodeId> {
108 let root_node = &self.nodes[scope];
109 let mut result = None;
110 query_selector::<&Node, QueryFirst>(
111 root_node,
112 selector_list,
113 &mut result,
114 self.may_use_invalidation_for(scope),
115 );
116
117 result.map(|node| node.id)
118 }
119
120 pub fn query_selector_all<'input>(
125 &self,
126 selector: &'input str,
127 ) -> Result<SmallVec<[NodeId; 32]>, ParseError<'input>> {
128 self.query_selector_all_in(self.root_node_id, selector)
129 }
130
131 pub fn query_selector_all_in<'input>(
141 &self,
142 scope: NodeId,
143 selector: &'input str,
144 ) -> Result<SmallVec<[NodeId; 32]>, ParseError<'input>> {
145 let selector_list = self.try_parse_selector_list(selector)?;
146 Ok(self.query_selector_all_in_raw(scope, &selector_list))
147 }
148
149 pub fn query_selector_all_raw(
156 &self,
157 selector_list: &SelectorList<SelectorImpl>,
158 ) -> SmallVec<[NodeId; 32]> {
159 self.query_selector_all_in_raw(self.root_node_id, selector_list)
160 }
161
162 pub fn query_selector_all_in_raw(
168 &self,
169 scope: NodeId,
170 selector_list: &SelectorList<SelectorImpl>,
171 ) -> SmallVec<[NodeId; 32]> {
172 let root_node = &self.nodes[scope];
173 let mut results = SmallVec::new();
174 query_selector::<&Node, QueryAll>(
175 root_node,
176 selector_list,
177 &mut results,
178 self.may_use_invalidation_for(scope),
179 );
180
181 results.iter().map(|node| node.id).collect()
182 }
183
184 fn may_use_invalidation_for(&self, scope: NodeId) -> MayUseInvalidation {
185 if scope == self.root_node_id {
186 MayUseInvalidation::Yes
187 } else {
188 MayUseInvalidation::No
189 }
190 }
191
192 pub fn matches_selector<'input>(
197 &self,
198 node_id: NodeId,
199 selector: &'input str,
200 ) -> Result<bool, ParseError<'input>> {
201 let selector_list = self.try_parse_selector_list(selector)?;
202 Ok(self.nodes[node_id].matches_selector_raw(&selector_list))
203 }
204
205 pub fn closest<'input>(
210 &self,
211 node_id: NodeId,
212 selector: &'input str,
213 ) -> Result<Option<NodeId>, ParseError<'input>> {
214 let selector_list = self.try_parse_selector_list(selector)?;
215 Ok(self.nodes[node_id].closest_raw(&selector_list))
216 }
217
218 pub fn try_parse_selector_list<'input>(
219 &self,
220 input: &'input str,
221 ) -> Result<SelectorList<SelectorImpl>, ParseError<'input>> {
222 let url_extra_data = self.url.url_extra_data();
223 SelectorParser::parse_author_origin_no_namespace(input, &url_extra_data)
224 }
225}
226
227impl Node {
228 pub fn query_selector_raw(&self, selector_list: &SelectorList<SelectorImpl>) -> Option<NodeId> {
236 let mut result = None;
237 query_selector::<&Node, QueryFirst>(
238 self,
239 selector_list,
240 &mut result,
241 MayUseInvalidation::No,
242 );
243 result.map(|node| node.id)
244 }
245
246 pub fn query_selector_all_raw(
254 &self,
255 selector_list: &SelectorList<SelectorImpl>,
256 ) -> SmallVec<[NodeId; 32]> {
257 let mut results = SmallVec::new();
258 query_selector::<&Node, QueryAll>(
259 self,
260 selector_list,
261 &mut results,
262 MayUseInvalidation::No,
263 );
264 results.iter().map(|node| node.id).collect()
265 }
266
267 pub fn matches_selector_raw(&self, selector_list: &SelectorList<SelectorImpl>) -> bool {
272 if !self.is_element() {
273 return false;
274 }
275
276 element_matches(&self, selector_list, self.owner_doc().quirks_mode())
277 }
278
279 pub fn closest_raw(&self, selector_list: &SelectorList<SelectorImpl>) -> Option<NodeId> {
283 if !self.is_element() {
284 return None;
285 }
286
287 element_closest(self, selector_list, self.owner_doc().quirks_mode()).map(|node| node.id)
288 }
289}