1use html5ever::{LocalName, Prefix, QualName, local_name, ns};
6use js::context::JSContext;
7use js::rust::HandleObject;
8use servo_config::pref;
9
10use crate::dom::bindings::error::{report_pending_exception, throw_dom_exception};
11use crate::dom::bindings::inheritance::Castable;
12use crate::dom::bindings::reflector::DomGlobal;
13use crate::dom::bindings::root::DomRoot;
14use crate::dom::customelementregistry::{
15 CustomElementRegistry, CustomElementState, is_valid_custom_element_name, upgrade_element,
16};
17use crate::dom::document::Document;
18use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator};
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::html::form_controls::htmlinputelement::HTMLInputElement;
21use crate::dom::html::htmlanchorelement::HTMLAnchorElement;
22use crate::dom::html::htmlareaelement::HTMLAreaElement;
23use crate::dom::html::htmlaudioelement::HTMLAudioElement;
24use crate::dom::html::htmlbaseelement::HTMLBaseElement;
25use crate::dom::html::htmlbodyelement::HTMLBodyElement;
26use crate::dom::html::htmlbrelement::HTMLBRElement;
27use crate::dom::html::htmlbuttonelement::HTMLButtonElement;
28use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
29use crate::dom::html::htmldataelement::HTMLDataElement;
30use crate::dom::html::htmldatalistelement::HTMLDataListElement;
31use crate::dom::html::htmldetailselement::HTMLDetailsElement;
32use crate::dom::html::htmldialogelement::HTMLDialogElement;
33use crate::dom::html::htmldirectoryelement::HTMLDirectoryElement;
34use crate::dom::html::htmldivelement::HTMLDivElement;
35use crate::dom::html::htmldlistelement::HTMLDListElement;
36use crate::dom::html::htmlelement::HTMLElement;
37use crate::dom::html::htmlembedelement::HTMLEmbedElement;
38use crate::dom::html::htmlfieldsetelement::HTMLFieldSetElement;
39use crate::dom::html::htmlfontelement::HTMLFontElement;
40use crate::dom::html::htmlformelement::HTMLFormElement;
41use crate::dom::html::htmlframeelement::HTMLFrameElement;
42use crate::dom::html::htmlframesetelement::HTMLFrameSetElement;
43use crate::dom::html::htmlheadelement::HTMLHeadElement;
44use crate::dom::html::htmlheadingelement::{HTMLHeadingElement, HeadingLevel};
45use crate::dom::html::htmlhrelement::HTMLHRElement;
46use crate::dom::html::htmlhtmlelement::HTMLHtmlElement;
47use crate::dom::html::htmliframeelement::HTMLIFrameElement;
48use crate::dom::html::htmlimageelement::HTMLImageElement;
49use crate::dom::html::htmllabelelement::HTMLLabelElement;
50use crate::dom::html::htmllegendelement::HTMLLegendElement;
51use crate::dom::html::htmllielement::HTMLLIElement;
52use crate::dom::html::htmllinkelement::HTMLLinkElement;
53use crate::dom::html::htmlmapelement::HTMLMapElement;
54use crate::dom::html::htmlmenuelement::HTMLMenuElement;
55use crate::dom::html::htmlmetaelement::HTMLMetaElement;
56use crate::dom::html::htmlmeterelement::HTMLMeterElement;
57use crate::dom::html::htmlmodelement::HTMLModElement;
58use crate::dom::html::htmlobjectelement::HTMLObjectElement;
59use crate::dom::html::htmlolistelement::HTMLOListElement;
60use crate::dom::html::htmloptgroupelement::HTMLOptGroupElement;
61use crate::dom::html::htmloptionelement::HTMLOptionElement;
62use crate::dom::html::htmloutputelement::HTMLOutputElement;
63use crate::dom::html::htmlparagraphelement::HTMLParagraphElement;
64use crate::dom::html::htmlparamelement::HTMLParamElement;
65use crate::dom::html::htmlpictureelement::HTMLPictureElement;
66use crate::dom::html::htmlpreelement::HTMLPreElement;
67use crate::dom::html::htmlprogresselement::HTMLProgressElement;
68use crate::dom::html::htmlquoteelement::HTMLQuoteElement;
69use crate::dom::html::htmlscriptelement::HTMLScriptElement;
70use crate::dom::html::htmlselectelement::HTMLSelectElement;
71use crate::dom::html::htmlslotelement::HTMLSlotElement;
72use crate::dom::html::htmlsourceelement::HTMLSourceElement;
73use crate::dom::html::htmlspanelement::HTMLSpanElement;
74use crate::dom::html::htmlstyleelement::HTMLStyleElement;
75use crate::dom::html::htmltablecaptionelement::HTMLTableCaptionElement;
76use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
77use crate::dom::html::htmltablecolelement::HTMLTableColElement;
78use crate::dom::html::htmltableelement::HTMLTableElement;
79use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
80use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
81use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
82use crate::dom::html::htmltextareaelement::HTMLTextAreaElement;
83use crate::dom::html::htmltimeelement::HTMLTimeElement;
84use crate::dom::html::htmltitleelement::HTMLTitleElement;
85use crate::dom::html::htmltrackelement::HTMLTrackElement;
86use crate::dom::html::htmlulistelement::HTMLUListElement;
87use crate::dom::html::htmlunknownelement::HTMLUnknownElement;
88use crate::dom::html::htmlvideoelement::HTMLVideoElement;
89use crate::dom::htmlmarqueeelement::HTMLMarqueeElement;
90use crate::dom::mathmlelement::MathMLElement;
91use crate::dom::svg::svgaelement::SVGAElement;
92use crate::dom::svg::svgcircleelement::SVGCircleElement;
93use crate::dom::svg::svgdefselement::SVGDefsElement;
94use crate::dom::svg::svgelement::SVGElement;
95use crate::dom::svg::svgellipseelement::SVGEllipseElement;
96use crate::dom::svg::svggelement::SVGGElement;
97use crate::dom::svg::svgimageelement::SVGImageElement;
98use crate::dom::svg::svglineargradientelement::SVGLinearGradientElement;
99use crate::dom::svg::svglineelement::SVGLineElement;
100use crate::dom::svg::svgpathelement::SVGPathElement;
101use crate::dom::svg::svgpatternelement::SVGPatternElement;
102use crate::dom::svg::svgpolygonelement::SVGPolygonElement;
103use crate::dom::svg::svgpolylineelement::SVGPolylineElement;
104use crate::dom::svg::svgradialgradientelement::SVGRadialGradientElement;
105use crate::dom::svg::svgrectelement::SVGRectElement;
106use crate::dom::svg::svgstopelement::SVGStopElement;
107use crate::dom::svg::svgsvgelement::SVGSVGElement;
108use crate::dom::svg::svgsymbolelement::SVGSymbolElement;
109use crate::dom::svg::svgtextelement::SVGTextElement;
110use crate::dom::svg::svgtspanelement::SVGTSpanElement;
111use crate::dom::svg::svguseelement::SVGUseElement;
112use crate::event_loop::script_thread::ScriptThread;
113use crate::realms::enter_auto_realm;
114
115fn create_svg_element(
116 cx: &mut JSContext,
117 name: QualName,
118 prefix: Option<Prefix>,
119 document: &Document,
120 proto: Option<HandleObject>,
121) -> DomRoot<Element> {
122 assert_eq!(name.ns, ns!(svg));
123
124 macro_rules! make(
125 ($ctor:ident) => ({
126 let obj = $ctor::new(cx, name.local, prefix, document, proto);
127 DomRoot::upcast(obj)
128 });
129 );
130
131 match name.local {
132 local_name!("a") => make!(SVGAElement),
133 local_name!("circle") => make!(SVGCircleElement),
134 local_name!("defs") => make!(SVGDefsElement),
135 local_name!("ellipse") => make!(SVGEllipseElement),
136 local_name!("g") => make!(SVGGElement),
137 local_name!("image") => make!(SVGImageElement),
138 local_name!("line") => make!(SVGLineElement),
139 local_name!("linearGradient") => make!(SVGLinearGradientElement),
140 local_name!("path") => make!(SVGPathElement),
141 local_name!("pattern") => make!(SVGPatternElement),
142 local_name!("polygon") => make!(SVGPolygonElement),
143 local_name!("polyline") => make!(SVGPolylineElement),
144 local_name!("radialGradient") => make!(SVGRadialGradientElement),
145 local_name!("stop") => make!(SVGStopElement),
146 local_name!("rect") => make!(SVGRectElement),
147 local_name!("svg") => make!(SVGSVGElement),
148 local_name!("symbol") => make!(SVGSymbolElement),
149 local_name!("text") => make!(SVGTextElement),
150 local_name!("tspan") => make!(SVGTSpanElement),
151 local_name!("use") => make!(SVGUseElement),
152 _ => make!(SVGElement),
153 }
154}
155
156fn create_mathml_element(
157 cx: &mut JSContext,
158 name: QualName,
159 prefix: Option<Prefix>,
160 document: &Document,
161 proto: Option<HandleObject>,
162) -> DomRoot<Element> {
163 assert_eq!(name.ns, ns!(mathml));
164
165 if pref!(mathml_core_enabled) {
166 let obj = MathMLElement::new(cx, name.local, prefix, document, proto);
167 DomRoot::upcast(obj)
168 } else {
169 Element::new(cx, name.local, name.ns, prefix, document, proto)
170 }
171}
172
173#[expect(clippy::too_many_arguments)]
175fn create_html_element(
176 cx: &mut JSContext,
177 name: QualName,
178 prefix: Option<Prefix>,
179 is: Option<LocalName>,
180 document: &Document,
181 creator: ElementCreator,
182 mode: CustomElementCreationMode,
183 proto: Option<HandleObject>,
184) -> DomRoot<Element> {
185 assert_eq!(name.ns, ns!(html));
186
187 let registry = CustomElementRegistry::lookup_a_custom_element_registry(document.upcast());
191
192 let definition = CustomElementRegistry::lookup_custom_element_definition(
195 registry.as_deref(),
196 &name.ns,
197 &name.local,
198 is.as_ref(),
199 );
200
201 if let Some(definition) = definition {
203 if !definition.is_autonomous() {
206 let element = create_native_html_element(cx, name, prefix, document, creator, proto);
210 element.set_is(definition.name.clone(), cx.no_gc());
211 element.set_custom_element_state(CustomElementState::Undefined, cx.no_gc());
212 element.set_custom_element_registry(registry.as_deref(), cx.no_gc());
213
214 match mode {
215 CustomElementCreationMode::Synchronous => {
217 upgrade_element(cx, definition, &element);
219 },
221 CustomElementCreationMode::Asynchronous => {
223 ScriptThread::enqueue_upgrade_reaction(cx, &element, definition)
224 },
225 }
226 return element;
227 } else {
228 match mode {
230 CustomElementCreationMode::Synchronous => {
233 let local_name = name.local;
234 return match definition.create_element(
237 cx,
238 document,
239 prefix.clone(),
240 registry.as_deref(),
241 ) {
242 Ok(element) => {
243 element.set_custom_element_definition(definition.clone(), cx.no_gc());
244 element
245 },
246 Err(error) => {
247 let global =
249 GlobalScope::current().unwrap_or_else(|| document.global());
250
251 let mut realm = enter_auto_realm(cx, &*global);
252 let cx = &mut realm.current_realm();
253
254 throw_dom_exception(cx, &global, error);
257 report_pending_exception(cx);
258
259 let element = DomRoot::upcast::<Element>(HTMLUnknownElement::new(
262 cx, local_name, prefix, document, proto,
263 ));
264 element
265 .set_custom_element_state(CustomElementState::Failed, cx.no_gc());
266 element.set_custom_element_registry(registry.as_deref(), cx.no_gc());
267 element
268 },
269 };
270 },
271 CustomElementCreationMode::Asynchronous => {
273 let result = DomRoot::upcast::<Element>(HTMLElement::new(
279 cx, name.local, prefix, document, proto,
280 ));
281 result.set_custom_element_state(CustomElementState::Undefined, cx.no_gc());
282 result.set_custom_element_registry(registry.as_deref(), cx.no_gc());
283 ScriptThread::enqueue_upgrade_reaction(cx, &result, definition);
285 return result;
286 },
287 }
288 }
289 }
290
291 let result = create_native_html_element(cx, name.clone(), prefix, document, creator, proto);
298 match is {
301 Some(is) => {
302 result.set_is(is, cx.no_gc());
303 result.set_custom_element_state(CustomElementState::Undefined, cx.no_gc());
304 result.set_custom_element_registry(registry.as_deref(), cx.no_gc());
305 },
306 None => {
307 if is_valid_custom_element_name(&name.local) {
308 result.set_custom_element_state(CustomElementState::Undefined, cx.no_gc());
309 result.set_custom_element_registry(registry.as_deref(), cx.no_gc());
310 } else {
311 result.set_initial_custom_element_state_to_uncustomized();
314 }
315 },
316 };
317
318 result
320}
321
322pub(crate) fn create_native_html_element(
323 cx: &mut JSContext,
324 name: QualName,
325 prefix: Option<Prefix>,
326 document: &Document,
327 creator: ElementCreator,
328 proto: Option<HandleObject>,
329) -> DomRoot<Element> {
330 assert_eq!(name.ns, ns!(html));
331
332 macro_rules! make(
333 ($ctor:ident) => ({
334 let obj = $ctor::new(cx, name.local, prefix, document, proto);
335 DomRoot::upcast(obj)
336 });
337 ($ctor:ident, $($arg:expr),+) => ({
338 let obj = $ctor::new(cx, name.local, prefix, document, proto, $($arg),+);
339 DomRoot::upcast(obj)
340 })
341 );
342
343 match name.local {
347 local_name!("a") => make!(HTMLAnchorElement),
348 local_name!("abbr") => make!(HTMLElement),
349 local_name!("acronym") => make!(HTMLElement),
350 local_name!("address") => make!(HTMLElement),
351 local_name!("area") => make!(HTMLAreaElement),
352 local_name!("article") => make!(HTMLElement),
353 local_name!("aside") => make!(HTMLElement),
354 local_name!("audio") => make!(HTMLAudioElement),
355 local_name!("b") => make!(HTMLElement),
356 local_name!("base") => make!(HTMLBaseElement),
357 local_name!("bdi") => make!(HTMLElement),
358 local_name!("bdo") => make!(HTMLElement),
359 local_name!("bgsound") => make!(HTMLUnknownElement),
361 local_name!("big") => make!(HTMLElement),
362 local_name!("blink") => make!(HTMLUnknownElement),
364 local_name!("blockquote") => make!(HTMLQuoteElement),
366 local_name!("body") => make!(HTMLBodyElement),
367 local_name!("br") => make!(HTMLBRElement),
368 local_name!("button") => make!(HTMLButtonElement),
369 local_name!("canvas") => make!(HTMLCanvasElement),
370 local_name!("caption") => make!(HTMLTableCaptionElement),
371 local_name!("center") => make!(HTMLElement),
372 local_name!("cite") => make!(HTMLElement),
373 local_name!("code") => make!(HTMLElement),
374 local_name!("col") => make!(HTMLTableColElement),
375 local_name!("colgroup") => make!(HTMLTableColElement),
376 local_name!("data") => make!(HTMLDataElement),
377 local_name!("datalist") => make!(HTMLDataListElement),
378 local_name!("dd") => make!(HTMLElement),
379 local_name!("del") => make!(HTMLModElement),
380 local_name!("details") => make!(HTMLDetailsElement),
381 local_name!("dfn") => make!(HTMLElement),
382 local_name!("dialog") => make!(HTMLDialogElement),
383 local_name!("dir") => make!(HTMLDirectoryElement),
384 local_name!("div") => make!(HTMLDivElement),
385 local_name!("dl") => make!(HTMLDListElement),
386 local_name!("dt") => make!(HTMLElement),
387 local_name!("em") => make!(HTMLElement),
388 local_name!("embed") => make!(HTMLEmbedElement),
389 local_name!("fieldset") => make!(HTMLFieldSetElement),
390 local_name!("figcaption") => make!(HTMLElement),
391 local_name!("figure") => make!(HTMLElement),
392 local_name!("font") => make!(HTMLFontElement),
393 local_name!("footer") => make!(HTMLElement),
394 local_name!("form") => make!(HTMLFormElement),
395 local_name!("frame") => make!(HTMLFrameElement),
396 local_name!("frameset") => make!(HTMLFrameSetElement),
397 local_name!("h1") => make!(HTMLHeadingElement, HeadingLevel::Heading1),
398 local_name!("h2") => make!(HTMLHeadingElement, HeadingLevel::Heading2),
399 local_name!("h3") => make!(HTMLHeadingElement, HeadingLevel::Heading3),
400 local_name!("h4") => make!(HTMLHeadingElement, HeadingLevel::Heading4),
401 local_name!("h5") => make!(HTMLHeadingElement, HeadingLevel::Heading5),
402 local_name!("h6") => make!(HTMLHeadingElement, HeadingLevel::Heading6),
403 local_name!("head") => make!(HTMLHeadElement),
404 local_name!("header") => make!(HTMLElement),
405 local_name!("hgroup") => make!(HTMLElement),
406 local_name!("hr") => make!(HTMLHRElement),
407 local_name!("html") => make!(HTMLHtmlElement),
408 local_name!("i") => make!(HTMLElement),
409 local_name!("iframe") => make!(HTMLIFrameElement),
410 local_name!("img") => make!(HTMLImageElement, creator),
411 local_name!("input") => make!(HTMLInputElement),
412 local_name!("ins") => make!(HTMLModElement),
413 local_name!("isindex") => make!(HTMLUnknownElement),
415 local_name!("kbd") => make!(HTMLElement),
416 local_name!("keygen") => make!(HTMLUnknownElement),
418 local_name!("label") => make!(HTMLLabelElement),
419 local_name!("legend") => make!(HTMLLegendElement),
420 local_name!("li") => make!(HTMLLIElement),
421 local_name!("link") => make!(HTMLLinkElement, creator),
422 local_name!("listing") => make!(HTMLPreElement),
424 local_name!("main") => make!(HTMLElement),
425 local_name!("map") => make!(HTMLMapElement),
426 local_name!("mark") => make!(HTMLElement),
427 local_name!("marquee") => make!(HTMLMarqueeElement),
428 local_name!("menu") => make!(HTMLMenuElement),
429 local_name!("meta") => make!(HTMLMetaElement),
430 local_name!("meter") => make!(HTMLMeterElement),
431 local_name!("multicol") => make!(HTMLUnknownElement),
433 local_name!("nav") => make!(HTMLElement),
434 local_name!("nextid") => make!(HTMLUnknownElement),
436 local_name!("nobr") => make!(HTMLElement),
437 local_name!("noframes") => make!(HTMLElement),
438 local_name!("noscript") => make!(HTMLElement),
439 local_name!("object") => make!(HTMLObjectElement),
440 local_name!("ol") => make!(HTMLOListElement),
441 local_name!("optgroup") => make!(HTMLOptGroupElement),
442 local_name!("option") => make!(HTMLOptionElement),
443 local_name!("output") => make!(HTMLOutputElement),
444 local_name!("p") => make!(HTMLParagraphElement),
445 local_name!("param") => make!(HTMLParamElement),
446 local_name!("picture") => make!(HTMLPictureElement),
447 local_name!("plaintext") => make!(HTMLPreElement),
448 local_name!("pre") => make!(HTMLPreElement),
449 local_name!("progress") => make!(HTMLProgressElement),
450 local_name!("q") => make!(HTMLQuoteElement),
451 local_name!("rp") => make!(HTMLElement),
452 local_name!("rt") => make!(HTMLElement),
453 local_name!("ruby") => make!(HTMLElement),
454 local_name!("s") => make!(HTMLElement),
455 local_name!("samp") => make!(HTMLElement),
456 local_name!("script") => make!(HTMLScriptElement, creator),
457 local_name!("section") => make!(HTMLElement),
458 local_name!("select") => make!(HTMLSelectElement),
459 local_name!("slot") => make!(HTMLSlotElement),
460 local_name!("small") => make!(HTMLElement),
461 local_name!("source") => make!(HTMLSourceElement),
462 local_name!("spacer") => make!(HTMLUnknownElement),
464 local_name!("span") => make!(HTMLSpanElement),
465 local_name!("strike") => make!(HTMLElement),
466 local_name!("strong") => make!(HTMLElement),
467 local_name!("style") => make!(HTMLStyleElement, creator),
468 local_name!("sub") => make!(HTMLElement),
469 local_name!("summary") => make!(HTMLElement),
470 local_name!("sup") => make!(HTMLElement),
471 local_name!("table") => make!(HTMLTableElement),
472 local_name!("tbody") => make!(HTMLTableSectionElement),
473 local_name!("td") => make!(HTMLTableCellElement),
474 local_name!("template") => make!(HTMLTemplateElement),
475 local_name!("textarea") => make!(HTMLTextAreaElement),
476 local_name!("tfoot") => make!(HTMLTableSectionElement),
478 local_name!("th") => make!(HTMLTableCellElement),
479 local_name!("thead") => make!(HTMLTableSectionElement),
481 local_name!("time") => make!(HTMLTimeElement),
482 local_name!("title") => make!(HTMLTitleElement, creator),
483 local_name!("tr") => make!(HTMLTableRowElement),
484 local_name!("tt") => make!(HTMLElement),
485 local_name!("track") => make!(HTMLTrackElement),
486 local_name!("u") => make!(HTMLElement),
487 local_name!("ul") => make!(HTMLUListElement),
488 local_name!("var") => make!(HTMLElement),
489 local_name!("video") => make!(HTMLVideoElement),
490 local_name!("wbr") => make!(HTMLElement),
491 local_name!("xmp") => make!(HTMLPreElement),
492 _ if is_valid_custom_element_name(&name.local) => make!(HTMLElement),
493 _ => make!(HTMLUnknownElement),
494 }
495}
496
497pub(crate) fn create_element(
498 cx: &mut JSContext,
499 name: QualName,
500 is: Option<LocalName>,
501 document: &Document,
502 creator: ElementCreator,
503 mode: CustomElementCreationMode,
504 proto: Option<HandleObject>,
505) -> DomRoot<Element> {
506 let prefix = name.prefix.clone();
507 match name.ns {
508 ns!(html) => create_html_element(cx, name, prefix, is, document, creator, mode, proto),
509 ns!(svg) => create_svg_element(cx, name, prefix, document, proto),
510 ns!(mathml) => create_mathml_element(cx, name, prefix, document, proto),
511 _ => Element::new(cx, name.local, name.ns, prefix, document, proto),
512 }
513}