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