Skip to main content

script/dom/node/
virtualmethods.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 html5ever::LocalName;
6use js::context::JSContext;
7use script_bindings::root::DomRoot;
8use style::attr::AttrValue;
9
10use crate::dom::bindings::inheritance::{
11    Castable, DocumentFragmentTypeId, ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId,
12    NodeTypeId, SVGElementTypeId, SVGGeometryElementTypeId, SVGGradientElementTypeId,
13    SVGGraphicsElementTypeId, SVGTextContentElementTypeId, SVGTextPositioningElementTypeId,
14};
15use crate::dom::bindings::str::DOMString;
16use crate::dom::document::Document;
17use crate::dom::documentfragment::DocumentFragment;
18use crate::dom::element::attributes::storage::AttrRef;
19use crate::dom::element::{AttributeMutation, Element};
20use crate::dom::event::Event;
21use crate::dom::html::form_controls::htmlinputelement::HTMLInputElement;
22use crate::dom::html::htmlanchorelement::HTMLAnchorElement;
23use crate::dom::html::htmlareaelement::HTMLAreaElement;
24use crate::dom::html::htmlbaseelement::HTMLBaseElement;
25use crate::dom::html::htmlbodyelement::HTMLBodyElement;
26use crate::dom::html::htmlbuttonelement::HTMLButtonElement;
27use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
28use crate::dom::html::htmldetailselement::HTMLDetailsElement;
29use crate::dom::html::htmlelement::HTMLElement;
30use crate::dom::html::htmlfieldsetelement::HTMLFieldSetElement;
31use crate::dom::html::htmlfontelement::HTMLFontElement;
32use crate::dom::html::htmlformelement::HTMLFormElement;
33use crate::dom::html::htmlheadelement::HTMLHeadElement;
34use crate::dom::html::htmlhrelement::HTMLHRElement;
35use crate::dom::html::htmliframeelement::HTMLIFrameElement;
36use crate::dom::html::htmlimageelement::HTMLImageElement;
37use crate::dom::html::htmllabelelement::HTMLLabelElement;
38use crate::dom::html::htmllielement::HTMLLIElement;
39use crate::dom::html::htmllinkelement::HTMLLinkElement;
40use crate::dom::html::htmlmarqueeelement::HTMLMarqueeElement;
41use crate::dom::html::htmlmediaelement::HTMLMediaElement;
42use crate::dom::html::htmlmetaelement::HTMLMetaElement;
43use crate::dom::html::htmlmeterelement::HTMLMeterElement;
44use crate::dom::html::htmlobjectelement::HTMLObjectElement;
45use crate::dom::html::htmloptgroupelement::HTMLOptGroupElement;
46use crate::dom::html::htmloptionelement::HTMLOptionElement;
47use crate::dom::html::htmloutputelement::HTMLOutputElement;
48use crate::dom::html::htmlpreelement::HTMLPreElement;
49use crate::dom::html::htmlprogresselement::HTMLProgressElement;
50use crate::dom::html::htmlscriptelement::HTMLScriptElement;
51use crate::dom::html::htmlselectelement::HTMLSelectElement;
52use crate::dom::html::htmlslotelement::HTMLSlotElement;
53use crate::dom::html::htmlsourceelement::HTMLSourceElement;
54use crate::dom::html::htmlstyleelement::HTMLStyleElement;
55use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
56use crate::dom::html::htmltablecolelement::HTMLTableColElement;
57use crate::dom::html::htmltableelement::HTMLTableElement;
58use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
59use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
60use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
61use crate::dom::html::htmltextareaelement::HTMLTextAreaElement;
62use crate::dom::html::htmltitleelement::HTMLTitleElement;
63use crate::dom::html::htmltrackelement::HTMLTrackElement;
64use crate::dom::html::htmlvideoelement::HTMLVideoElement;
65use crate::dom::htmlbuttonelement::CommandState;
66use crate::dom::htmldialogelement::HTMLDialogElement;
67use crate::dom::node::{
68    BindContext, ChildrenMutation, CloneChildrenFlag, MoveContext, Node, UnbindContext,
69};
70use crate::dom::shadowroot::shadowroot::ShadowRoot;
71use crate::dom::svg::svgaelement::SVGAElement;
72use crate::dom::svg::svgcircleelement::SVGCircleElement;
73use crate::dom::svg::svgdefselement::SVGDefsElement;
74use crate::dom::svg::svgelement::SVGElement;
75use crate::dom::svg::svgellipseelement::SVGEllipseElement;
76use crate::dom::svg::svggelement::SVGGElement;
77use crate::dom::svg::svgimageelement::SVGImageElement;
78use crate::dom::svg::svglineargradientelement::SVGLinearGradientElement;
79use crate::dom::svg::svglineelement::SVGLineElement;
80use crate::dom::svg::svgpathelement::SVGPathElement;
81use crate::dom::svg::svgpatternelement::SVGPatternElement;
82use crate::dom::svg::svgpolygonelement::SVGPolygonElement;
83use crate::dom::svg::svgpolylineelement::SVGPolylineElement;
84use crate::dom::svg::svgradialgradientelement::SVGRadialGradientElement;
85use crate::dom::svg::svgrectelement::SVGRectElement;
86use crate::dom::svg::svgstopelement::SVGStopElement;
87use crate::dom::svg::svgsvgelement::SVGSVGElement;
88use crate::dom::svg::svgsymbolelement::SVGSymbolElement;
89use crate::dom::svg::svgtextelement::SVGTextElement;
90use crate::dom::svg::svgtspanelement::SVGTSpanElement;
91use crate::dom::svg::svguseelement::SVGUseElement;
92
93/// Trait to allow DOM nodes to opt-in to overriding (or adding to) common
94/// behaviours. Replicates the effect of C++ virtual methods.
95pub(crate) trait VirtualMethods {
96    /// Returns self as the superclass of the implementation for this trait,
97    /// if any.
98    fn super_type(&self) -> Option<&dyn VirtualMethods>;
99
100    /// Called when attributes of a node are mutated.
101    /// <https://dom.spec.whatwg.org/#attribute-is-set>
102    /// <https://dom.spec.whatwg.org/#attribute-is-removed>
103    fn attribute_mutated(
104        &self,
105        cx: &mut js::context::JSContext,
106        attr: AttrRef<'_>,
107        mutation: AttributeMutation,
108    ) {
109        if let Some(s) = self.super_type() {
110            s.attribute_mutated(cx, attr, mutation);
111        }
112    }
113
114    /// Returns `true` if given attribute `attr` affects style of the
115    /// given element.
116    fn attribute_affects_presentational_hints(&self, attr: AttrRef<'_>) -> bool {
117        match self.super_type() {
118            Some(s) => s.attribute_affects_presentational_hints(attr),
119            None => false,
120        }
121    }
122
123    /// Returns the right AttrValue variant for the attribute with name `name`
124    /// on this element.
125    fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
126        match self.super_type() {
127            Some(s) => s.parse_plain_attribute(name, value),
128            _ => AttrValue::String(value.into()),
129        }
130    }
131
132    /// Invoked during a DOM tree mutation after a node becomes connected, once all
133    /// related DOM tree mutations have been applied.
134    /// <https://dom.spec.whatwg.org/#concept-node-post-connection-ext>
135    fn post_connection_steps(&self, cx: &mut JSContext) {
136        if let Some(s) = self.super_type() {
137            s.post_connection_steps(cx);
138        }
139    }
140
141    /// <https://dom.spec.whatwg.org/#concept-node-move-ext>
142    fn moving_steps(&self, cx: &mut JSContext, context: &MoveContext) {
143        if let Some(s) = self.super_type() {
144            s.moving_steps(cx, context);
145        }
146    }
147
148    /// Called when a Node is appended to a tree.
149    fn bind_to_tree(&self, cx: &mut JSContext, context: &BindContext) {
150        if let Some(s) = self.super_type() {
151            s.bind_to_tree(cx, context);
152        }
153    }
154
155    /// Called when a Node is removed from a tree.
156    /// Implements removing steps:
157    /// <https://dom.spec.whatwg.org/#concept-node-remove-ext>
158    fn unbind_from_tree(&self, cx: &mut js::context::JSContext, context: &UnbindContext) {
159        if let Some(s) = self.super_type() {
160            s.unbind_from_tree(cx, context);
161        }
162    }
163
164    /// Called on the parent when its children are changed.
165    fn children_changed(&self, cx: &mut JSContext, mutation: &ChildrenMutation) {
166        if let Some(s) = self.super_type() {
167            s.children_changed(cx, mutation);
168        }
169    }
170
171    /// Called during event dispatch after the bubbling phase completes.
172    fn handle_event(&self, cx: &mut js::context::JSContext, event: &Event) {
173        if let Some(s) = self.super_type() {
174            s.handle_event(cx, event);
175        }
176    }
177
178    /// <https://html.spec.whatwg.org/multipage/#is-valid-command-steps>
179    fn is_valid_command_steps(&self, command: CommandState) -> bool {
180        self.super_type()
181            .is_some_and(|super_type| super_type.is_valid_command_steps(command))
182    }
183
184    /// <https://html.spec.whatwg.org/multipage/#command-steps>
185    fn command_steps(
186        &self,
187        cx: &mut js::context::JSContext,
188        button: DomRoot<HTMLButtonElement>,
189        command: CommandState,
190    ) -> bool {
191        self.super_type()
192            .is_some_and(|super_type| super_type.command_steps(cx, button, command))
193    }
194
195    /// <https://dom.spec.whatwg.org/#concept-node-adopt-ext>
196    fn adopting_steps(&self, cx: &mut JSContext, old_doc: &Document) {
197        if let Some(s) = self.super_type() {
198            s.adopting_steps(cx, old_doc);
199        }
200    }
201
202    /// <https://dom.spec.whatwg.org/#concept-node-clone-ext>
203    fn cloning_steps(
204        &self,
205        cx: &mut JSContext,
206        copy: &Node,
207        maybe_doc: Option<&Document>,
208        clone_children: CloneChildrenFlag,
209    ) {
210        if let Some(s) = self.super_type() {
211            s.cloning_steps(cx, copy, maybe_doc, clone_children);
212        }
213    }
214
215    /// Called on an element when it is popped off the stack of open elements
216    /// of a parser.
217    fn pop(&self, cx: &mut js::context::JSContext) {
218        if let Some(s) = self.super_type() {
219            s.pop(cx);
220        }
221    }
222}
223
224/// Obtain a VirtualMethods instance for a given Node-derived object. Any
225/// method call on the trait object will invoke the corresponding method on the
226/// concrete type, propagating up the parent hierarchy unless otherwise
227/// interrupted.
228pub(crate) fn vtable_for(node: &Node) -> &dyn VirtualMethods {
229    match node.type_id() {
230        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => {
231            node.downcast::<HTMLAnchorElement>().unwrap() as &dyn VirtualMethods
232        },
233        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAreaElement)) => {
234            node.downcast::<HTMLAreaElement>().unwrap() as &dyn VirtualMethods
235        },
236        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBaseElement)) => {
237            node.downcast::<HTMLBaseElement>().unwrap() as &dyn VirtualMethods
238        },
239        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)) => {
240            node.downcast::<HTMLBodyElement>().unwrap() as &dyn VirtualMethods
241        },
242        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) => {
243            node.downcast::<HTMLButtonElement>().unwrap() as &dyn VirtualMethods
244        },
245        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement)) => {
246            node.downcast::<HTMLCanvasElement>().unwrap() as &dyn VirtualMethods
247        },
248        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDetailsElement)) => {
249            node.downcast::<HTMLDetailsElement>().unwrap() as &dyn VirtualMethods
250        },
251        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDialogElement)) => {
252            node.downcast::<HTMLDialogElement>().unwrap() as &dyn VirtualMethods
253        },
254        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement)) => {
255            node.downcast::<HTMLFieldSetElement>().unwrap() as &dyn VirtualMethods
256        },
257        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFontElement)) => {
258            node.downcast::<HTMLFontElement>().unwrap() as &dyn VirtualMethods
259        },
260        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFormElement)) => {
261            node.downcast::<HTMLFormElement>().unwrap() as &dyn VirtualMethods
262        },
263        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement)) => {
264            node.downcast::<HTMLHeadElement>().unwrap() as &dyn VirtualMethods
265        },
266        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHRElement)) => {
267            node.downcast::<HTMLHRElement>().unwrap() as &dyn VirtualMethods
268        },
269        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement)) => {
270            node.downcast::<HTMLImageElement>().unwrap() as &dyn VirtualMethods
271        },
272        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement)) => {
273            node.downcast::<HTMLIFrameElement>().unwrap() as &dyn VirtualMethods
274        },
275        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
276            node.downcast::<HTMLInputElement>().unwrap() as &dyn VirtualMethods
277        },
278        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement)) => {
279            node.downcast::<HTMLLabelElement>().unwrap() as &dyn VirtualMethods
280        },
281        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLIElement)) => {
282            node.downcast::<HTMLLIElement>().unwrap() as &dyn VirtualMethods
283        },
284        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLinkElement)) => {
285            node.downcast::<HTMLLinkElement>().unwrap() as &dyn VirtualMethods
286        },
287        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMarqueeElement)) => {
288            node.downcast::<HTMLMarqueeElement>().unwrap() as &dyn VirtualMethods
289        },
290        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(
291            media_el,
292        ))) => match media_el {
293            HTMLMediaElementTypeId::HTMLVideoElement => {
294                node.downcast::<HTMLVideoElement>().unwrap() as &dyn VirtualMethods
295            },
296            _ => node.downcast::<HTMLMediaElement>().unwrap() as &dyn VirtualMethods,
297        },
298        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMetaElement)) => {
299            node.downcast::<HTMLMetaElement>().unwrap() as &dyn VirtualMethods
300        },
301        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMeterElement)) => {
302            node.downcast::<HTMLMeterElement>().unwrap() as &dyn VirtualMethods
303        },
304        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)) => {
305            node.downcast::<HTMLObjectElement>().unwrap() as &dyn VirtualMethods
306        },
307        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement)) => {
308            node.downcast::<HTMLOptGroupElement>().unwrap() as &dyn VirtualMethods
309        },
310        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) => {
311            node.downcast::<HTMLOptionElement>().unwrap() as &dyn VirtualMethods
312        },
313        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
314            node.downcast::<HTMLOutputElement>().unwrap() as &dyn VirtualMethods
315        },
316        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement)) => {
317            node.downcast::<HTMLPreElement>().unwrap() as &dyn VirtualMethods
318        },
319        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLProgressElement)) => {
320            node.downcast::<HTMLProgressElement>().unwrap() as &dyn VirtualMethods
321        },
322        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLScriptElement)) => {
323            node.downcast::<HTMLScriptElement>().unwrap() as &dyn VirtualMethods
324        },
325        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) => {
326            node.downcast::<HTMLSelectElement>().unwrap() as &dyn VirtualMethods
327        },
328        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSourceElement)) => {
329            node.downcast::<HTMLSourceElement>().unwrap() as &dyn VirtualMethods
330        },
331        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSlotElement)) => {
332            node.downcast::<HTMLSlotElement>().unwrap() as &dyn VirtualMethods
333        },
334        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLStyleElement)) => {
335            node.downcast::<HTMLStyleElement>().unwrap() as &dyn VirtualMethods
336        },
337        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement)) => {
338            node.downcast::<HTMLTableElement>().unwrap() as &dyn VirtualMethods
339        },
340        NodeTypeId::Element(ElementTypeId::HTMLElement(
341            HTMLElementTypeId::HTMLTableCellElement,
342        )) => node.downcast::<HTMLTableCellElement>().unwrap() as &dyn VirtualMethods,
343        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement)) => {
344            node.downcast::<HTMLTableColElement>().unwrap() as &dyn VirtualMethods
345        },
346        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement)) => {
347            node.downcast::<HTMLTableRowElement>().unwrap() as &dyn VirtualMethods
348        },
349        NodeTypeId::Element(ElementTypeId::HTMLElement(
350            HTMLElementTypeId::HTMLTableSectionElement,
351        )) => node.downcast::<HTMLTableSectionElement>().unwrap() as &dyn VirtualMethods,
352        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTemplateElement)) => {
353            node.downcast::<HTMLTemplateElement>().unwrap() as &dyn VirtualMethods
354        },
355        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
356            node.downcast::<HTMLTextAreaElement>().unwrap() as &dyn VirtualMethods
357        },
358        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement)) => {
359            node.downcast::<HTMLTitleElement>().unwrap() as &dyn VirtualMethods
360        },
361        NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTrackElement)) => {
362            node.downcast::<HTMLTrackElement>().unwrap() as &dyn VirtualMethods
363        },
364        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
365            SVGGraphicsElementTypeId::SVGGeometryElement(
366                SVGGeometryElementTypeId::SVGCircleElement,
367            ),
368        ))) => node.downcast::<SVGCircleElement>().unwrap() as &dyn VirtualMethods,
369        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
370            SVGGraphicsElementTypeId::SVGGeometryElement(
371                SVGGeometryElementTypeId::SVGEllipseElement,
372            ),
373        ))) => node.downcast::<SVGEllipseElement>().unwrap() as &dyn VirtualMethods,
374        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
375            SVGGraphicsElementTypeId::SVGImageElement,
376        ))) => node.downcast::<SVGImageElement>().unwrap() as &dyn VirtualMethods,
377        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
378            SVGGraphicsElementTypeId::SVGTextContentElement(
379                SVGTextContentElementTypeId::SVGTextPositioningElement(
380                    SVGTextPositioningElementTypeId::SVGTextElement,
381                ),
382            ),
383        ))) => node.downcast::<SVGTextElement>().unwrap() as &dyn VirtualMethods,
384        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
385            SVGGraphicsElementTypeId::SVGTextContentElement(
386                SVGTextContentElementTypeId::SVGTextPositioningElement(
387                    SVGTextPositioningElementTypeId::SVGTSpanElement,
388                ),
389            ),
390        ))) => node.downcast::<SVGTSpanElement>().unwrap() as &dyn VirtualMethods,
391        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
392            SVGGraphicsElementTypeId::SVGGeometryElement(SVGGeometryElementTypeId::SVGRectElement),
393        ))) => node.downcast::<SVGRectElement>().unwrap() as &dyn VirtualMethods,
394        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
395            SVGGraphicsElementTypeId::SVGGeometryElement(SVGGeometryElementTypeId::SVGLineElement),
396        ))) => node.downcast::<SVGLineElement>().unwrap() as &dyn VirtualMethods,
397        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
398            SVGGraphicsElementTypeId::SVGGeometryElement(
399                SVGGeometryElementTypeId::SVGPolylineElement,
400            ),
401        ))) => node.downcast::<SVGPolylineElement>().unwrap() as &dyn VirtualMethods,
402        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
403            SVGGraphicsElementTypeId::SVGGeometryElement(
404                SVGGeometryElementTypeId::SVGPolygonElement,
405            ),
406        ))) => node.downcast::<SVGPolygonElement>().unwrap() as &dyn VirtualMethods,
407        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
408            SVGGraphicsElementTypeId::SVGGeometryElement(SVGGeometryElementTypeId::SVGPathElement),
409        ))) => node.downcast::<SVGPathElement>().unwrap() as &dyn VirtualMethods,
410        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
411            SVGGraphicsElementTypeId::SVGSVGElement,
412        ))) => node.downcast::<SVGSVGElement>().unwrap() as &dyn VirtualMethods,
413        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
414            SVGGraphicsElementTypeId::SVGGElement,
415        ))) => node.downcast::<SVGGElement>().unwrap() as &dyn VirtualMethods,
416        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
417            SVGGraphicsElementTypeId::SVGUseElement,
418        ))) => node.downcast::<SVGUseElement>().unwrap() as &dyn VirtualMethods,
419        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
420            SVGGraphicsElementTypeId::SVGSymbolElement,
421        ))) => node.downcast::<SVGSymbolElement>().unwrap() as &dyn VirtualMethods,
422        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
423            SVGGraphicsElementTypeId::SVGDefsElement,
424        ))) => node.downcast::<SVGDefsElement>().unwrap() as &dyn VirtualMethods,
425        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGradientElement(
426            SVGGradientElementTypeId::SVGLinearGradientElement,
427        ))) => node.downcast::<SVGLinearGradientElement>().unwrap() as &dyn VirtualMethods,
428        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGradientElement(
429            SVGGradientElementTypeId::SVGRadialGradientElement,
430        ))) => node.downcast::<SVGRadialGradientElement>().unwrap() as &dyn VirtualMethods,
431        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGStopElement)) => {
432            node.downcast::<SVGStopElement>().unwrap() as &dyn VirtualMethods
433        },
434        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGPatternElement)) => {
435            node.downcast::<SVGPatternElement>().unwrap() as &dyn VirtualMethods
436        },
437        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
438            SVGGraphicsElementTypeId::SVGAElement,
439        ))) => node.downcast::<SVGAElement>().unwrap() as &dyn VirtualMethods,
440        NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGElement)) => {
441            node.downcast::<SVGElement>().unwrap() as &dyn VirtualMethods
442        },
443        NodeTypeId::Element(ElementTypeId::Element) => {
444            node.downcast::<Element>().unwrap() as &dyn VirtualMethods
445        },
446        NodeTypeId::Element(_) => node.downcast::<HTMLElement>().unwrap() as &dyn VirtualMethods,
447        NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => {
448            node.downcast::<ShadowRoot>().unwrap() as &dyn VirtualMethods
449        },
450        NodeTypeId::DocumentFragment(_) => {
451            node.downcast::<DocumentFragment>().unwrap() as &dyn VirtualMethods
452        },
453        _ => node as &dyn VirtualMethods,
454    }
455}