1use html5ever::LocalName;
6use script_bindings::script_runtime::CanGc;
7use style::attr::AttrValue;
8
9use crate::dom::attr::Attr;
10use crate::dom::bindings::inheritance::{
11 Castable, DocumentFragmentTypeId, ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId,
12 NodeTypeId, SVGElementTypeId, SVGGraphicsElementTypeId,
13};
14use crate::dom::bindings::str::DOMString;
15use crate::dom::document::Document;
16use crate::dom::documentfragment::DocumentFragment;
17use crate::dom::element::{AttributeMutation, Element};
18use crate::dom::event::Event;
19use crate::dom::html::htmlanchorelement::HTMLAnchorElement;
20use crate::dom::html::htmlareaelement::HTMLAreaElement;
21use crate::dom::html::htmlbaseelement::HTMLBaseElement;
22use crate::dom::html::htmlbodyelement::HTMLBodyElement;
23use crate::dom::html::htmlbuttonelement::HTMLButtonElement;
24use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
25use crate::dom::html::htmldetailselement::HTMLDetailsElement;
26use crate::dom::html::htmlelement::HTMLElement;
27use crate::dom::html::htmlfieldsetelement::HTMLFieldSetElement;
28use crate::dom::html::htmlfontelement::HTMLFontElement;
29use crate::dom::html::htmlformelement::HTMLFormElement;
30use crate::dom::html::htmlheadelement::HTMLHeadElement;
31use crate::dom::html::htmlhrelement::HTMLHRElement;
32use crate::dom::html::htmliframeelement::HTMLIFrameElement;
33use crate::dom::html::htmlimageelement::HTMLImageElement;
34use crate::dom::html::htmlinputelement::HTMLInputElement;
35use crate::dom::html::htmllabelelement::HTMLLabelElement;
36use crate::dom::html::htmllielement::HTMLLIElement;
37use crate::dom::html::htmllinkelement::HTMLLinkElement;
38use crate::dom::html::htmlmediaelement::HTMLMediaElement;
39use crate::dom::html::htmlmetaelement::HTMLMetaElement;
40use crate::dom::html::htmlmeterelement::HTMLMeterElement;
41use crate::dom::html::htmlobjectelement::HTMLObjectElement;
42use crate::dom::html::htmloptgroupelement::HTMLOptGroupElement;
43use crate::dom::html::htmloptionelement::HTMLOptionElement;
44use crate::dom::html::htmloutputelement::HTMLOutputElement;
45use crate::dom::html::htmlpreelement::HTMLPreElement;
46use crate::dom::html::htmlprogresselement::HTMLProgressElement;
47use crate::dom::html::htmlscriptelement::HTMLScriptElement;
48use crate::dom::html::htmlselectelement::HTMLSelectElement;
49use crate::dom::html::htmlslotelement::HTMLSlotElement;
50use crate::dom::html::htmlsourceelement::HTMLSourceElement;
51use crate::dom::html::htmlstyleelement::HTMLStyleElement;
52use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
53use crate::dom::html::htmltablecolelement::HTMLTableColElement;
54use crate::dom::html::htmltableelement::HTMLTableElement;
55use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
56use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
57use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
58use crate::dom::html::htmltextareaelement::HTMLTextAreaElement;
59use crate::dom::html::htmltitleelement::HTMLTitleElement;
60use crate::dom::html::htmlvideoelement::HTMLVideoElement;
61use crate::dom::node::{BindContext, ChildrenMutation, CloneChildrenFlag, Node, UnbindContext};
62use crate::dom::shadowroot::ShadowRoot;
63use crate::dom::svg::svgelement::SVGElement;
64use crate::dom::svg::svgimageelement::SVGImageElement;
65use crate::dom::svg::svgsvgelement::SVGSVGElement;
66
67pub(crate) trait VirtualMethods {
70 fn super_type(&self) -> Option<&dyn VirtualMethods>;
73
74 fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
78 if let Some(s) = self.super_type() {
79 s.attribute_mutated(attr, mutation, can_gc);
80 }
81 }
82
83 fn attribute_affects_presentational_hints(&self, attr: &Attr) -> bool {
86 match self.super_type() {
87 Some(s) => s.attribute_affects_presentational_hints(attr),
88 None => false,
89 }
90 }
91
92 fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
95 match self.super_type() {
96 Some(s) => s.parse_plain_attribute(name, value),
97 _ => AttrValue::String(value.into()),
98 }
99 }
100
101 fn post_connection_steps(&self, can_gc: CanGc) {
105 if let Some(s) = self.super_type() {
106 s.post_connection_steps(can_gc);
107 }
108 }
109
110 fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
112 if let Some(s) = self.super_type() {
113 s.bind_to_tree(context, can_gc);
114 }
115 }
116
117 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
121 if let Some(s) = self.super_type() {
122 s.unbind_from_tree(context, can_gc);
123 }
124 }
125
126 fn children_changed(&self, mutation: &ChildrenMutation, can_gc: CanGc) {
128 if let Some(s) = self.super_type() {
129 s.children_changed(mutation, can_gc);
130 }
131 }
132
133 fn handle_event(&self, event: &Event, can_gc: CanGc) {
135 if let Some(s) = self.super_type() {
136 s.handle_event(event, can_gc);
137 }
138 }
139
140 fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
142 if let Some(s) = self.super_type() {
143 s.adopting_steps(old_doc, can_gc);
144 }
145 }
146
147 fn cloning_steps(
149 &self,
150 copy: &Node,
151 maybe_doc: Option<&Document>,
152 clone_children: CloneChildrenFlag,
153 can_gc: CanGc,
154 ) {
155 if let Some(s) = self.super_type() {
156 s.cloning_steps(copy, maybe_doc, clone_children, can_gc);
157 }
158 }
159
160 fn pop(&self) {
163 if let Some(s) = self.super_type() {
164 s.pop();
165 }
166 }
167}
168
169pub(crate) fn vtable_for(node: &Node) -> &dyn VirtualMethods {
174 match node.type_id() {
175 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => {
176 node.downcast::<HTMLAnchorElement>().unwrap() as &dyn VirtualMethods
177 },
178 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAreaElement)) => {
179 node.downcast::<HTMLAreaElement>().unwrap() as &dyn VirtualMethods
180 },
181 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBaseElement)) => {
182 node.downcast::<HTMLBaseElement>().unwrap() as &dyn VirtualMethods
183 },
184 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)) => {
185 node.downcast::<HTMLBodyElement>().unwrap() as &dyn VirtualMethods
186 },
187 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) => {
188 node.downcast::<HTMLButtonElement>().unwrap() as &dyn VirtualMethods
189 },
190 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement)) => {
191 node.downcast::<HTMLCanvasElement>().unwrap() as &dyn VirtualMethods
192 },
193 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDetailsElement)) => {
194 node.downcast::<HTMLDetailsElement>().unwrap() as &dyn VirtualMethods
195 },
196 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement)) => {
197 node.downcast::<HTMLFieldSetElement>().unwrap() as &dyn VirtualMethods
198 },
199 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFontElement)) => {
200 node.downcast::<HTMLFontElement>().unwrap() as &dyn VirtualMethods
201 },
202 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFormElement)) => {
203 node.downcast::<HTMLFormElement>().unwrap() as &dyn VirtualMethods
204 },
205 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement)) => {
206 node.downcast::<HTMLHeadElement>().unwrap() as &dyn VirtualMethods
207 },
208 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHRElement)) => {
209 node.downcast::<HTMLHRElement>().unwrap() as &dyn VirtualMethods
210 },
211 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement)) => {
212 node.downcast::<HTMLImageElement>().unwrap() as &dyn VirtualMethods
213 },
214 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement)) => {
215 node.downcast::<HTMLIFrameElement>().unwrap() as &dyn VirtualMethods
216 },
217 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
218 node.downcast::<HTMLInputElement>().unwrap() as &dyn VirtualMethods
219 },
220 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement)) => {
221 node.downcast::<HTMLLabelElement>().unwrap() as &dyn VirtualMethods
222 },
223 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLIElement)) => {
224 node.downcast::<HTMLLIElement>().unwrap() as &dyn VirtualMethods
225 },
226 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLinkElement)) => {
227 node.downcast::<HTMLLinkElement>().unwrap() as &dyn VirtualMethods
228 },
229 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(
230 media_el,
231 ))) => match media_el {
232 HTMLMediaElementTypeId::HTMLVideoElement => {
233 node.downcast::<HTMLVideoElement>().unwrap() as &dyn VirtualMethods
234 },
235 _ => node.downcast::<HTMLMediaElement>().unwrap() as &dyn VirtualMethods,
236 },
237 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMetaElement)) => {
238 node.downcast::<HTMLMetaElement>().unwrap() as &dyn VirtualMethods
239 },
240 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMeterElement)) => {
241 node.downcast::<HTMLMeterElement>().unwrap() as &dyn VirtualMethods
242 },
243 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)) => {
244 node.downcast::<HTMLObjectElement>().unwrap() as &dyn VirtualMethods
245 },
246 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement)) => {
247 node.downcast::<HTMLOptGroupElement>().unwrap() as &dyn VirtualMethods
248 },
249 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) => {
250 node.downcast::<HTMLOptionElement>().unwrap() as &dyn VirtualMethods
251 },
252 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
253 node.downcast::<HTMLOutputElement>().unwrap() as &dyn VirtualMethods
254 },
255 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement)) => {
256 node.downcast::<HTMLPreElement>().unwrap() as &dyn VirtualMethods
257 },
258 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLProgressElement)) => {
259 node.downcast::<HTMLProgressElement>().unwrap() as &dyn VirtualMethods
260 },
261 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLScriptElement)) => {
262 node.downcast::<HTMLScriptElement>().unwrap() as &dyn VirtualMethods
263 },
264 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) => {
265 node.downcast::<HTMLSelectElement>().unwrap() as &dyn VirtualMethods
266 },
267 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSourceElement)) => {
268 node.downcast::<HTMLSourceElement>().unwrap() as &dyn VirtualMethods
269 },
270 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSlotElement)) => {
271 node.downcast::<HTMLSlotElement>().unwrap() as &dyn VirtualMethods
272 },
273 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLStyleElement)) => {
274 node.downcast::<HTMLStyleElement>().unwrap() as &dyn VirtualMethods
275 },
276 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement)) => {
277 node.downcast::<HTMLTableElement>().unwrap() as &dyn VirtualMethods
278 },
279 NodeTypeId::Element(ElementTypeId::HTMLElement(
280 HTMLElementTypeId::HTMLTableCellElement,
281 )) => node.downcast::<HTMLTableCellElement>().unwrap() as &dyn VirtualMethods,
282 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement)) => {
283 node.downcast::<HTMLTableColElement>().unwrap() as &dyn VirtualMethods
284 },
285 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement)) => {
286 node.downcast::<HTMLTableRowElement>().unwrap() as &dyn VirtualMethods
287 },
288 NodeTypeId::Element(ElementTypeId::HTMLElement(
289 HTMLElementTypeId::HTMLTableSectionElement,
290 )) => node.downcast::<HTMLTableSectionElement>().unwrap() as &dyn VirtualMethods,
291 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTemplateElement)) => {
292 node.downcast::<HTMLTemplateElement>().unwrap() as &dyn VirtualMethods
293 },
294 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
295 node.downcast::<HTMLTextAreaElement>().unwrap() as &dyn VirtualMethods
296 },
297 NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement)) => {
298 node.downcast::<HTMLTitleElement>().unwrap() as &dyn VirtualMethods
299 },
300 NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
301 SVGGraphicsElementTypeId::SVGImageElement,
302 ))) => node.downcast::<SVGImageElement>().unwrap() as &dyn VirtualMethods,
303 NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
304 SVGGraphicsElementTypeId::SVGSVGElement,
305 ))) => node.downcast::<SVGSVGElement>().unwrap() as &dyn VirtualMethods,
306 NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGElement)) => {
307 node.downcast::<SVGElement>().unwrap() as &dyn VirtualMethods
308 },
309 NodeTypeId::Element(ElementTypeId::Element) => {
310 node.downcast::<Element>().unwrap() as &dyn VirtualMethods
311 },
312 NodeTypeId::Element(_) => node.downcast::<HTMLElement>().unwrap() as &dyn VirtualMethods,
313 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => {
314 node.downcast::<ShadowRoot>().unwrap() as &dyn VirtualMethods
315 },
316 NodeTypeId::DocumentFragment(_) => {
317 node.downcast::<DocumentFragment>().unwrap() as &dyn VirtualMethods
318 },
319 _ => node as &dyn VirtualMethods,
320 }
321}