1use html5ever::{LocalName, Prefix, QualName, local_name, ns};
6use js::rust::HandleObject;
7
8use crate::dom::bindings::error::{report_pending_exception, throw_dom_exception};
9use crate::dom::bindings::reflector::DomGlobal;
10use crate::dom::bindings::root::DomRoot;
11use crate::dom::customelementregistry::{
12 CustomElementState, is_valid_custom_element_name, upgrade_element,
13};
14use crate::dom::document::Document;
15use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator};
16use crate::dom::globalscope::GlobalScope;
17use crate::dom::html::htmlanchorelement::HTMLAnchorElement;
18use crate::dom::html::htmlareaelement::HTMLAreaElement;
19use crate::dom::html::htmlaudioelement::HTMLAudioElement;
20use crate::dom::html::htmlbaseelement::HTMLBaseElement;
21use crate::dom::html::htmlbodyelement::HTMLBodyElement;
22use crate::dom::html::htmlbrelement::HTMLBRElement;
23use crate::dom::html::htmlbuttonelement::HTMLButtonElement;
24use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
25use crate::dom::html::htmldataelement::HTMLDataElement;
26use crate::dom::html::htmldatalistelement::HTMLDataListElement;
27use crate::dom::html::htmldetailselement::HTMLDetailsElement;
28use crate::dom::html::htmldialogelement::HTMLDialogElement;
29use crate::dom::html::htmldirectoryelement::HTMLDirectoryElement;
30use crate::dom::html::htmldivelement::HTMLDivElement;
31use crate::dom::html::htmldlistelement::HTMLDListElement;
32use crate::dom::html::htmlelement::HTMLElement;
33use crate::dom::html::htmlembedelement::HTMLEmbedElement;
34use crate::dom::html::htmlfieldsetelement::HTMLFieldSetElement;
35use crate::dom::html::htmlfontelement::HTMLFontElement;
36use crate::dom::html::htmlformelement::HTMLFormElement;
37use crate::dom::html::htmlframeelement::HTMLFrameElement;
38use crate::dom::html::htmlframesetelement::HTMLFrameSetElement;
39use crate::dom::html::htmlheadelement::HTMLHeadElement;
40use crate::dom::html::htmlheadingelement::{HTMLHeadingElement, HeadingLevel};
41use crate::dom::html::htmlhrelement::HTMLHRElement;
42use crate::dom::html::htmlhtmlelement::HTMLHtmlElement;
43use crate::dom::html::htmliframeelement::HTMLIFrameElement;
44use crate::dom::html::htmlimageelement::HTMLImageElement;
45use crate::dom::html::htmlinputelement::HTMLInputElement;
46use crate::dom::html::htmllabelelement::HTMLLabelElement;
47use crate::dom::html::htmllegendelement::HTMLLegendElement;
48use crate::dom::html::htmllielement::HTMLLIElement;
49use crate::dom::html::htmllinkelement::HTMLLinkElement;
50use crate::dom::html::htmlmapelement::HTMLMapElement;
51use crate::dom::html::htmlmenuelement::HTMLMenuElement;
52use crate::dom::html::htmlmetaelement::HTMLMetaElement;
53use crate::dom::html::htmlmeterelement::HTMLMeterElement;
54use crate::dom::html::htmlmodelement::HTMLModElement;
55use crate::dom::html::htmlobjectelement::HTMLObjectElement;
56use crate::dom::html::htmlolistelement::HTMLOListElement;
57use crate::dom::html::htmloptgroupelement::HTMLOptGroupElement;
58use crate::dom::html::htmloptionelement::HTMLOptionElement;
59use crate::dom::html::htmloutputelement::HTMLOutputElement;
60use crate::dom::html::htmlparagraphelement::HTMLParagraphElement;
61use crate::dom::html::htmlparamelement::HTMLParamElement;
62use crate::dom::html::htmlpictureelement::HTMLPictureElement;
63use crate::dom::html::htmlpreelement::HTMLPreElement;
64use crate::dom::html::htmlprogresselement::HTMLProgressElement;
65use crate::dom::html::htmlquoteelement::HTMLQuoteElement;
66use crate::dom::html::htmlscriptelement::HTMLScriptElement;
67use crate::dom::html::htmlselectelement::HTMLSelectElement;
68use crate::dom::html::htmlslotelement::HTMLSlotElement;
69use crate::dom::html::htmlsourceelement::HTMLSourceElement;
70use crate::dom::html::htmlspanelement::HTMLSpanElement;
71use crate::dom::html::htmlstyleelement::HTMLStyleElement;
72use crate::dom::html::htmltablecaptionelement::HTMLTableCaptionElement;
73use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
74use crate::dom::html::htmltablecolelement::HTMLTableColElement;
75use crate::dom::html::htmltableelement::HTMLTableElement;
76use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
77use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
78use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
79use crate::dom::html::htmltextareaelement::HTMLTextAreaElement;
80use crate::dom::html::htmltimeelement::HTMLTimeElement;
81use crate::dom::html::htmltitleelement::HTMLTitleElement;
82use crate::dom::html::htmltrackelement::HTMLTrackElement;
83use crate::dom::html::htmlulistelement::HTMLUListElement;
84use crate::dom::html::htmlunknownelement::HTMLUnknownElement;
85use crate::dom::html::htmlvideoelement::HTMLVideoElement;
86use crate::dom::svg::svgelement::SVGElement;
87use crate::dom::svg::svgimageelement::SVGImageElement;
88use crate::dom::svg::svgsvgelement::SVGSVGElement;
89use crate::realms::{InRealm, enter_realm};
90use crate::script_runtime::CanGc;
91use crate::script_thread::ScriptThread;
92
93fn create_svg_element(
94 name: QualName,
95 prefix: Option<Prefix>,
96 document: &Document,
97 proto: Option<HandleObject>,
98) -> DomRoot<Element> {
99 assert_eq!(name.ns, ns!(svg));
100
101 macro_rules! make(
102 ($ctor:ident) => ({
103 let obj = $ctor::new(name.local, prefix, document, proto, CanGc::note());
104 DomRoot::upcast(obj)
105 });
106 ($ctor:ident, $($arg:expr),+) => ({
107 let obj = $ctor::new(name.local, prefix, document, proto, $($arg),+, CanGc::note());
108 DomRoot::upcast(obj)
109 })
110 );
111
112 match name.local {
113 local_name!("image") => make!(SVGImageElement),
114 local_name!("svg") => make!(SVGSVGElement),
115 _ => make!(SVGElement),
116 }
117}
118
119#[expect(clippy::too_many_arguments)]
121fn create_html_element(
122 name: QualName,
123 prefix: Option<Prefix>,
124 is: Option<LocalName>,
125 document: &Document,
126 creator: ElementCreator,
127 mode: CustomElementCreationMode,
128 proto: Option<HandleObject>,
129 can_gc: CanGc,
130) -> DomRoot<Element> {
131 assert_eq!(name.ns, ns!(html));
132
133 let definition = document.lookup_custom_element_definition(&name.ns, &name.local, is.as_ref());
136
137 if let Some(definition) = definition {
139 if !definition.is_autonomous() {
142 let element = create_native_html_element(name, prefix, document, creator, proto);
146 element.set_is(definition.name.clone());
147 element.set_custom_element_state(CustomElementState::Undefined);
148
149 match mode {
150 CustomElementCreationMode::Synchronous => {
152 upgrade_element(definition, &element, can_gc);
154 },
156 CustomElementCreationMode::Asynchronous => {
158 ScriptThread::enqueue_upgrade_reaction(&element, definition)
159 },
160 }
161 return element;
162 } else {
163 match mode {
165 CustomElementCreationMode::Synchronous => {
168 let local_name = name.local.clone();
169 return match definition.create_element(document, prefix.clone(), can_gc) {
172 Ok(element) => {
173 element.set_custom_element_definition(definition.clone());
174 element
175 },
176 Err(error) => {
177 let global =
179 GlobalScope::current().unwrap_or_else(|| document.global());
180 let cx = GlobalScope::get_cx();
181
182 let ar = enter_realm(&*global);
186 throw_dom_exception(cx, &global, error, can_gc);
187 report_pending_exception(cx, true, InRealm::Entered(&ar), can_gc);
188
189 let element = DomRoot::upcast::<Element>(HTMLUnknownElement::new(
195 local_name, prefix, document, proto, can_gc,
196 ));
197 element.set_custom_element_state(CustomElementState::Failed);
198 element
199 },
200 };
201 },
202 CustomElementCreationMode::Asynchronous => {
204 let result = DomRoot::upcast::<Element>(HTMLElement::new(
210 name.local.clone(),
211 prefix.clone(),
212 document,
213 proto,
214 can_gc,
215 ));
216 result.set_custom_element_state(CustomElementState::Undefined);
217 ScriptThread::enqueue_upgrade_reaction(&result, definition);
219 return result;
220 },
221 }
222 }
223 }
224
225 let result = create_native_html_element(name.clone(), prefix, document, creator, proto);
232 match is {
235 Some(is) => {
236 result.set_is(is);
237 result.set_custom_element_state(CustomElementState::Undefined);
238 },
239 None => {
240 if is_valid_custom_element_name(&name.local) {
241 result.set_custom_element_state(CustomElementState::Undefined);
242 } else {
243 result.set_initial_custom_element_state_to_uncustomized();
246 }
247 },
248 };
249
250 result
252}
253
254pub(crate) fn create_native_html_element(
255 name: QualName,
256 prefix: Option<Prefix>,
257 document: &Document,
258 creator: ElementCreator,
259 proto: Option<HandleObject>,
260) -> DomRoot<Element> {
261 assert_eq!(name.ns, ns!(html));
262
263 macro_rules! make(
264 ($ctor:ident) => ({
265 let obj = $ctor::new(name.local, prefix, document, proto, CanGc::note());
266 DomRoot::upcast(obj)
267 });
268 ($ctor:ident, $($arg:expr),+) => ({
269 let obj = $ctor::new(name.local, prefix, document, proto, $($arg),+, CanGc::note());
270 DomRoot::upcast(obj)
271 })
272 );
273
274 match name.local {
278 local_name!("a") => make!(HTMLAnchorElement),
279 local_name!("abbr") => make!(HTMLElement),
280 local_name!("acronym") => make!(HTMLElement),
281 local_name!("address") => make!(HTMLElement),
282 local_name!("area") => make!(HTMLAreaElement),
283 local_name!("article") => make!(HTMLElement),
284 local_name!("aside") => make!(HTMLElement),
285 local_name!("audio") => make!(HTMLAudioElement),
286 local_name!("b") => make!(HTMLElement),
287 local_name!("base") => make!(HTMLBaseElement),
288 local_name!("bdi") => make!(HTMLElement),
289 local_name!("bdo") => make!(HTMLElement),
290 local_name!("bgsound") => make!(HTMLUnknownElement),
292 local_name!("big") => make!(HTMLElement),
293 local_name!("blink") => make!(HTMLUnknownElement),
295 local_name!("blockquote") => make!(HTMLQuoteElement),
297 local_name!("body") => make!(HTMLBodyElement),
298 local_name!("br") => make!(HTMLBRElement),
299 local_name!("button") => make!(HTMLButtonElement),
300 local_name!("canvas") => make!(HTMLCanvasElement),
301 local_name!("caption") => make!(HTMLTableCaptionElement),
302 local_name!("center") => make!(HTMLElement),
303 local_name!("cite") => make!(HTMLElement),
304 local_name!("code") => make!(HTMLElement),
305 local_name!("col") => make!(HTMLTableColElement),
306 local_name!("colgroup") => make!(HTMLTableColElement),
307 local_name!("data") => make!(HTMLDataElement),
308 local_name!("datalist") => make!(HTMLDataListElement),
309 local_name!("dd") => make!(HTMLElement),
310 local_name!("del") => make!(HTMLModElement),
311 local_name!("details") => make!(HTMLDetailsElement),
312 local_name!("dfn") => make!(HTMLElement),
313 local_name!("dialog") => make!(HTMLDialogElement),
314 local_name!("dir") => make!(HTMLDirectoryElement),
315 local_name!("div") => make!(HTMLDivElement),
316 local_name!("dl") => make!(HTMLDListElement),
317 local_name!("dt") => make!(HTMLElement),
318 local_name!("em") => make!(HTMLElement),
319 local_name!("embed") => make!(HTMLEmbedElement),
320 local_name!("fieldset") => make!(HTMLFieldSetElement),
321 local_name!("figcaption") => make!(HTMLElement),
322 local_name!("figure") => make!(HTMLElement),
323 local_name!("font") => make!(HTMLFontElement),
324 local_name!("footer") => make!(HTMLElement),
325 local_name!("form") => make!(HTMLFormElement),
326 local_name!("frame") => make!(HTMLFrameElement),
327 local_name!("frameset") => make!(HTMLFrameSetElement),
328 local_name!("h1") => make!(HTMLHeadingElement, HeadingLevel::Heading1),
329 local_name!("h2") => make!(HTMLHeadingElement, HeadingLevel::Heading2),
330 local_name!("h3") => make!(HTMLHeadingElement, HeadingLevel::Heading3),
331 local_name!("h4") => make!(HTMLHeadingElement, HeadingLevel::Heading4),
332 local_name!("h5") => make!(HTMLHeadingElement, HeadingLevel::Heading5),
333 local_name!("h6") => make!(HTMLHeadingElement, HeadingLevel::Heading6),
334 local_name!("head") => make!(HTMLHeadElement),
335 local_name!("header") => make!(HTMLElement),
336 local_name!("hgroup") => make!(HTMLElement),
337 local_name!("hr") => make!(HTMLHRElement),
338 local_name!("html") => make!(HTMLHtmlElement),
339 local_name!("i") => make!(HTMLElement),
340 local_name!("iframe") => make!(HTMLIFrameElement),
341 local_name!("img") => make!(HTMLImageElement, creator),
342 local_name!("input") => make!(HTMLInputElement),
343 local_name!("ins") => make!(HTMLModElement),
344 local_name!("isindex") => make!(HTMLUnknownElement),
346 local_name!("kbd") => make!(HTMLElement),
347 local_name!("keygen") => make!(HTMLUnknownElement),
349 local_name!("label") => make!(HTMLLabelElement),
350 local_name!("legend") => make!(HTMLLegendElement),
351 local_name!("li") => make!(HTMLLIElement),
352 local_name!("link") => make!(HTMLLinkElement, creator),
353 local_name!("listing") => make!(HTMLPreElement),
355 local_name!("main") => make!(HTMLElement),
356 local_name!("map") => make!(HTMLMapElement),
357 local_name!("mark") => make!(HTMLElement),
358 local_name!("marquee") => make!(HTMLElement),
359 local_name!("menu") => make!(HTMLMenuElement),
360 local_name!("meta") => make!(HTMLMetaElement),
361 local_name!("meter") => make!(HTMLMeterElement),
362 local_name!("multicol") => make!(HTMLUnknownElement),
364 local_name!("nav") => make!(HTMLElement),
365 local_name!("nextid") => make!(HTMLUnknownElement),
367 local_name!("nobr") => make!(HTMLElement),
368 local_name!("noframes") => make!(HTMLElement),
369 local_name!("noscript") => make!(HTMLElement),
370 local_name!("object") => make!(HTMLObjectElement),
371 local_name!("ol") => make!(HTMLOListElement),
372 local_name!("optgroup") => make!(HTMLOptGroupElement),
373 local_name!("option") => make!(HTMLOptionElement),
374 local_name!("output") => make!(HTMLOutputElement),
375 local_name!("p") => make!(HTMLParagraphElement),
376 local_name!("param") => make!(HTMLParamElement),
377 local_name!("picture") => make!(HTMLPictureElement),
378 local_name!("plaintext") => make!(HTMLPreElement),
379 local_name!("pre") => make!(HTMLPreElement),
380 local_name!("progress") => make!(HTMLProgressElement),
381 local_name!("q") => make!(HTMLQuoteElement),
382 local_name!("rp") => make!(HTMLElement),
383 local_name!("rt") => make!(HTMLElement),
384 local_name!("ruby") => make!(HTMLElement),
385 local_name!("s") => make!(HTMLElement),
386 local_name!("samp") => make!(HTMLElement),
387 local_name!("script") => make!(HTMLScriptElement, creator),
388 local_name!("section") => make!(HTMLElement),
389 local_name!("select") => make!(HTMLSelectElement),
390 local_name!("slot") => make!(HTMLSlotElement),
391 local_name!("small") => make!(HTMLElement),
392 local_name!("source") => make!(HTMLSourceElement),
393 local_name!("spacer") => make!(HTMLUnknownElement),
395 local_name!("span") => make!(HTMLSpanElement),
396 local_name!("strike") => make!(HTMLElement),
397 local_name!("strong") => make!(HTMLElement),
398 local_name!("style") => make!(HTMLStyleElement, creator),
399 local_name!("sub") => make!(HTMLElement),
400 local_name!("summary") => make!(HTMLElement),
401 local_name!("sup") => make!(HTMLElement),
402 local_name!("table") => make!(HTMLTableElement),
403 local_name!("tbody") => make!(HTMLTableSectionElement),
404 local_name!("td") => make!(HTMLTableCellElement),
405 local_name!("template") => make!(HTMLTemplateElement),
406 local_name!("textarea") => make!(HTMLTextAreaElement),
407 local_name!("tfoot") => make!(HTMLTableSectionElement),
409 local_name!("th") => make!(HTMLTableCellElement),
410 local_name!("thead") => make!(HTMLTableSectionElement),
412 local_name!("time") => make!(HTMLTimeElement),
413 local_name!("title") => make!(HTMLTitleElement),
414 local_name!("tr") => make!(HTMLTableRowElement),
415 local_name!("tt") => make!(HTMLElement),
416 local_name!("track") => make!(HTMLTrackElement),
417 local_name!("u") => make!(HTMLElement),
418 local_name!("ul") => make!(HTMLUListElement),
419 local_name!("var") => make!(HTMLElement),
420 local_name!("video") => make!(HTMLVideoElement),
421 local_name!("wbr") => make!(HTMLElement),
422 local_name!("xmp") => make!(HTMLPreElement),
423 _ if is_valid_custom_element_name(&name.local) => make!(HTMLElement),
424 _ => make!(HTMLUnknownElement),
425 }
426}
427
428pub(crate) fn create_element(
429 name: QualName,
430 is: Option<LocalName>,
431 document: &Document,
432 creator: ElementCreator,
433 mode: CustomElementCreationMode,
434 proto: Option<HandleObject>,
435 can_gc: CanGc,
436) -> DomRoot<Element> {
437 let prefix = name.prefix.clone();
438 match name.ns {
439 ns!(html) => create_html_element(name, prefix, is, document, creator, mode, proto, can_gc),
440 ns!(svg) => create_svg_element(name, prefix, document, proto),
441 _ => Element::new(name.local, name.ns, prefix, document, proto, can_gc),
442 }
443}