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, ServoLayoutDomTypeBundle, 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(Some(format!(
56 "'{selector}' is an invalid selector"
57 ))));
58 };
59
60 query_selector::<ServoDangerousStyleElement<'dom>, Query>(
63 self,
64 &selector_list,
65 &mut result,
66 MayUseInvalidation::No,
67 );
68
69 Ok(result)
70 }
71}
72
73impl<'dom> From<LayoutDom<'dom, Node>> for ServoDangerousStyleNode<'dom> {
74 fn from(node: LayoutDom<'dom, Node>) -> Self {
75 Self { node }
76 }
77}
78
79impl<'dom> DangerousStyleNode<'dom> for ServoDangerousStyleNode<'dom> {
80 type ConcreteTypeBundle = ServoLayoutDomTypeBundle<'dom>;
81
82 fn layout_node(&self) -> ServoLayoutNode<'dom> {
83 self.node.into()
84 }
85}
86
87impl NodeInfo for ServoDangerousStyleNode<'_> {
88 fn is_element(&self) -> bool {
89 self.node.is_element_for_layout()
90 }
91
92 fn is_text_node(&self) -> bool {
93 self.node.is_text_node_for_layout()
94 }
95}
96
97impl<'dom> TNode for ServoDangerousStyleNode<'dom> {
98 type ConcreteDocument = ServoDangerousStyleDocument<'dom>;
99 type ConcreteElement = ServoDangerousStyleElement<'dom>;
100 type ConcreteShadowRoot = ServoDangerousStyleShadowRoot<'dom>;
101
102 fn parent_node(&self) -> Option<Self> {
103 self.node.parent_node_ref().map(Into::into)
104 }
105
106 fn first_child(&self) -> Option<Self> {
107 self.node.first_child_ref().map(Into::into)
108 }
109
110 fn last_child(&self) -> Option<Self> {
111 self.node.last_child_ref().map(Into::into)
112 }
113
114 fn prev_sibling(&self) -> Option<Self> {
115 self.node.prev_sibling_ref().map(Into::into)
116 }
117
118 fn next_sibling(&self) -> Option<Self> {
119 self.node.next_sibling_ref().map(Into::into)
120 }
121
122 fn owner_doc(&self) -> Self::ConcreteDocument {
123 self.node.owner_doc_for_layout().into()
124 }
125
126 fn traversal_parent(&self) -> Option<ServoDangerousStyleElement<'dom>> {
127 Some(self.node.traversal_parent()?.into())
128 }
129
130 fn opaque(&self) -> style::dom::OpaqueNode {
131 self.node.opaque()
132 }
133
134 fn debug_id(self) -> usize {
135 self.opaque().0
136 }
137
138 fn as_element(&self) -> Option<ServoDangerousStyleElement<'dom>> {
139 Some(self.node.downcast()?.into())
140 }
141
142 fn as_document(&self) -> Option<ServoDangerousStyleDocument<'dom>> {
143 self.node.downcast().map(Into::into)
144 }
145
146 fn as_shadow_root(&self) -> Option<ServoDangerousStyleShadowRoot<'dom>> {
147 self.node.downcast().map(Into::into)
148 }
149
150 fn is_in_document(&self) -> bool {
151 unsafe { self.node.get_flag(NodeFlags::IS_IN_A_DOCUMENT_TREE) }
152 }
153}