1use 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
90pub(crate) trait VirtualMethods {
93 fn super_type(&self) -> Option<&dyn VirtualMethods>;
96
97 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 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 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 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 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 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 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 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 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 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 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 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 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 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 fn pop(&self, cx: &mut js::context::JSContext) {
229 if let Some(s) = self.super_type() {
230 s.pop(cx);
231 }
232 }
233}
234
235pub(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}