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