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