script/layout_dom/
servo_dangerous_style_node.rs1#![expect(unsafe_code)]
6#![deny(missing_docs)]
7
8use layout_api::DangerousStyleNode;
9use script_bindings::error::Fallible;
10use servo_arc::Arc;
11use style;
12use style::dom::{NodeInfo, TNode};
13use style::dom_apis::{MayUseInvalidation, SelectorQuery, query_selector};
14use style::selector_parser::SelectorParser;
15use style::stylesheets::UrlExtraData;
16use url::Url;
17
18use super::{ServoDangerousStyleDocument, ServoDangerousStyleShadowRoot};
19use crate::dom::bindings::error::Error;
20use crate::dom::bindings::root::LayoutDom;
21use crate::dom::node::{Node, NodeFlags};
22use crate::layout_dom::{ServoDangerousStyleElement, ServoLayoutNode};
23
24#[derive(Copy, Clone, Debug, Eq, PartialEq)]
28#[repr(transparent)]
29pub struct ServoDangerousStyleNode<'dom> {
30 pub(crate) node: LayoutDom<'dom, Node>,
31}
32
33unsafe impl Send for ServoDangerousStyleNode<'_> {}
34unsafe impl Sync for ServoDangerousStyleNode<'_> {}
35
36impl<'dom> ServoDangerousStyleNode<'dom> {
37 pub(crate) fn scope_match_a_selectors_string<Query>(
39 self,
40 document_url: Arc<Url>,
41 selector: &str,
42 ) -> Fallible<Query::Output>
43 where
44 Query: SelectorQuery<ServoDangerousStyleElement<'dom>>,
45 Query::Output: Default,
46 {
47 let mut result = Query::Output::default();
48
49 let selector_or_error =
51 SelectorParser::parse_author_origin_no_namespace(selector, &UrlExtraData(document_url));
52
53 let Ok(selector_list) = selector_or_error else {
55 return Err(Error::Syntax(None));
56 };
57
58 query_selector::<ServoDangerousStyleElement<'dom>, Query>(
61 self,
62 &selector_list,
63 &mut result,
64 MayUseInvalidation::No,
65 );
66
67 Ok(result)
68 }
69}
70
71impl<'dom> From<LayoutDom<'dom, Node>> for ServoDangerousStyleNode<'dom> {
72 fn from(node: LayoutDom<'dom, Node>) -> Self {
73 Self { node }
74 }
75}
76
77impl<'dom> DangerousStyleNode<'dom> for ServoDangerousStyleNode<'dom> {
78 type ConcreteLayoutNode = ServoLayoutNode<'dom>;
79
80 fn layout_node(&self) -> Self::ConcreteLayoutNode {
81 self.node.into()
82 }
83}
84
85impl NodeInfo for ServoDangerousStyleNode<'_> {
86 fn is_element(&self) -> bool {
87 self.node.is_element_for_layout()
88 }
89
90 fn is_text_node(&self) -> bool {
91 self.node.is_text_node_for_layout()
92 }
93}
94
95impl<'dom> TNode for ServoDangerousStyleNode<'dom> {
96 type ConcreteDocument = ServoDangerousStyleDocument<'dom>;
97 type ConcreteElement = ServoDangerousStyleElement<'dom>;
98 type ConcreteShadowRoot = ServoDangerousStyleShadowRoot<'dom>;
99
100 fn parent_node(&self) -> Option<Self> {
101 self.node.parent_node_ref().map(Into::into)
102 }
103
104 fn first_child(&self) -> Option<Self> {
105 self.node.first_child_ref().map(Into::into)
106 }
107
108 fn last_child(&self) -> Option<Self> {
109 self.node.last_child_ref().map(Into::into)
110 }
111
112 fn prev_sibling(&self) -> Option<Self> {
113 self.node.prev_sibling_ref().map(Into::into)
114 }
115
116 fn next_sibling(&self) -> Option<Self> {
117 self.node.next_sibling_ref().map(Into::into)
118 }
119
120 fn owner_doc(&self) -> Self::ConcreteDocument {
121 self.node.owner_doc_for_layout().into()
122 }
123
124 fn traversal_parent(&self) -> Option<ServoDangerousStyleElement<'dom>> {
125 Some(self.node.traversal_parent()?.into())
126 }
127
128 fn opaque(&self) -> style::dom::OpaqueNode {
129 self.node.opaque()
130 }
131
132 fn debug_id(self) -> usize {
133 self.opaque().0
134 }
135
136 fn as_element(&self) -> Option<ServoDangerousStyleElement<'dom>> {
137 Some(self.node.downcast()?.into())
138 }
139
140 fn as_document(&self) -> Option<ServoDangerousStyleDocument<'dom>> {
141 self.node.downcast().map(Into::into)
142 }
143
144 fn as_shadow_root(&self) -> Option<ServoDangerousStyleShadowRoot<'dom>> {
145 self.node.downcast().map(Into::into)
146 }
147
148 fn is_in_document(&self) -> bool {
149 unsafe { self.node.get_flag(NodeFlags::IS_IN_A_DOCUMENT_TREE) }
150 }
151}