/src/serenity/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2020-2023, Luke Wilde <lukew@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibWeb/DOM/Document.h> |
9 | | #include <LibWeb/DOM/ElementFactory.h> |
10 | | #include <LibWeb/HTML/CustomElements/CustomElementDefinition.h> |
11 | | #include <LibWeb/HTML/CustomElements/CustomElementName.h> |
12 | | #include <LibWeb/HTML/HTMLAnchorElement.h> |
13 | | #include <LibWeb/HTML/HTMLAreaElement.h> |
14 | | #include <LibWeb/HTML/HTMLAudioElement.h> |
15 | | #include <LibWeb/HTML/HTMLBRElement.h> |
16 | | #include <LibWeb/HTML/HTMLBaseElement.h> |
17 | | #include <LibWeb/HTML/HTMLBodyElement.h> |
18 | | #include <LibWeb/HTML/HTMLButtonElement.h> |
19 | | #include <LibWeb/HTML/HTMLCanvasElement.h> |
20 | | #include <LibWeb/HTML/HTMLDListElement.h> |
21 | | #include <LibWeb/HTML/HTMLDataElement.h> |
22 | | #include <LibWeb/HTML/HTMLDataListElement.h> |
23 | | #include <LibWeb/HTML/HTMLDetailsElement.h> |
24 | | #include <LibWeb/HTML/HTMLDialogElement.h> |
25 | | #include <LibWeb/HTML/HTMLDirectoryElement.h> |
26 | | #include <LibWeb/HTML/HTMLDivElement.h> |
27 | | #include <LibWeb/HTML/HTMLEmbedElement.h> |
28 | | #include <LibWeb/HTML/HTMLFieldSetElement.h> |
29 | | #include <LibWeb/HTML/HTMLFontElement.h> |
30 | | #include <LibWeb/HTML/HTMLFormElement.h> |
31 | | #include <LibWeb/HTML/HTMLFrameElement.h> |
32 | | #include <LibWeb/HTML/HTMLFrameSetElement.h> |
33 | | #include <LibWeb/HTML/HTMLHRElement.h> |
34 | | #include <LibWeb/HTML/HTMLHeadElement.h> |
35 | | #include <LibWeb/HTML/HTMLHeadingElement.h> |
36 | | #include <LibWeb/HTML/HTMLHtmlElement.h> |
37 | | #include <LibWeb/HTML/HTMLIFrameElement.h> |
38 | | #include <LibWeb/HTML/HTMLImageElement.h> |
39 | | #include <LibWeb/HTML/HTMLInputElement.h> |
40 | | #include <LibWeb/HTML/HTMLLIElement.h> |
41 | | #include <LibWeb/HTML/HTMLLabelElement.h> |
42 | | #include <LibWeb/HTML/HTMLLegendElement.h> |
43 | | #include <LibWeb/HTML/HTMLLinkElement.h> |
44 | | #include <LibWeb/HTML/HTMLMapElement.h> |
45 | | #include <LibWeb/HTML/HTMLMarqueeElement.h> |
46 | | #include <LibWeb/HTML/HTMLMenuElement.h> |
47 | | #include <LibWeb/HTML/HTMLMetaElement.h> |
48 | | #include <LibWeb/HTML/HTMLMeterElement.h> |
49 | | #include <LibWeb/HTML/HTMLModElement.h> |
50 | | #include <LibWeb/HTML/HTMLOListElement.h> |
51 | | #include <LibWeb/HTML/HTMLObjectElement.h> |
52 | | #include <LibWeb/HTML/HTMLOptGroupElement.h> |
53 | | #include <LibWeb/HTML/HTMLOptionElement.h> |
54 | | #include <LibWeb/HTML/HTMLOutputElement.h> |
55 | | #include <LibWeb/HTML/HTMLParagraphElement.h> |
56 | | #include <LibWeb/HTML/HTMLParamElement.h> |
57 | | #include <LibWeb/HTML/HTMLPictureElement.h> |
58 | | #include <LibWeb/HTML/HTMLPreElement.h> |
59 | | #include <LibWeb/HTML/HTMLProgressElement.h> |
60 | | #include <LibWeb/HTML/HTMLQuoteElement.h> |
61 | | #include <LibWeb/HTML/HTMLScriptElement.h> |
62 | | #include <LibWeb/HTML/HTMLSelectElement.h> |
63 | | #include <LibWeb/HTML/HTMLSlotElement.h> |
64 | | #include <LibWeb/HTML/HTMLSourceElement.h> |
65 | | #include <LibWeb/HTML/HTMLSpanElement.h> |
66 | | #include <LibWeb/HTML/HTMLStyleElement.h> |
67 | | #include <LibWeb/HTML/HTMLSummaryElement.h> |
68 | | #include <LibWeb/HTML/HTMLTableCaptionElement.h> |
69 | | #include <LibWeb/HTML/HTMLTableCellElement.h> |
70 | | #include <LibWeb/HTML/HTMLTableColElement.h> |
71 | | #include <LibWeb/HTML/HTMLTableElement.h> |
72 | | #include <LibWeb/HTML/HTMLTableRowElement.h> |
73 | | #include <LibWeb/HTML/HTMLTableSectionElement.h> |
74 | | #include <LibWeb/HTML/HTMLTemplateElement.h> |
75 | | #include <LibWeb/HTML/HTMLTextAreaElement.h> |
76 | | #include <LibWeb/HTML/HTMLTimeElement.h> |
77 | | #include <LibWeb/HTML/HTMLTitleElement.h> |
78 | | #include <LibWeb/HTML/HTMLTrackElement.h> |
79 | | #include <LibWeb/HTML/HTMLUListElement.h> |
80 | | #include <LibWeb/HTML/HTMLUnknownElement.h> |
81 | | #include <LibWeb/HTML/HTMLVideoElement.h> |
82 | | #include <LibWeb/HTML/Scripting/ExceptionReporter.h> |
83 | | #include <LibWeb/Infra/Strings.h> |
84 | | #include <LibWeb/MathML/MathMLElement.h> |
85 | | #include <LibWeb/MathML/TagNames.h> |
86 | | #include <LibWeb/Namespace.h> |
87 | | #include <LibWeb/SVG/SVGAElement.h> |
88 | | #include <LibWeb/SVG/SVGCircleElement.h> |
89 | | #include <LibWeb/SVG/SVGClipPathElement.h> |
90 | | #include <LibWeb/SVG/SVGDefsElement.h> |
91 | | #include <LibWeb/SVG/SVGDescElement.h> |
92 | | #include <LibWeb/SVG/SVGEllipseElement.h> |
93 | | #include <LibWeb/SVG/SVGForeignObjectElement.h> |
94 | | #include <LibWeb/SVG/SVGGElement.h> |
95 | | #include <LibWeb/SVG/SVGImageElement.h> |
96 | | #include <LibWeb/SVG/SVGLineElement.h> |
97 | | #include <LibWeb/SVG/SVGLinearGradientElement.h> |
98 | | #include <LibWeb/SVG/SVGMaskElement.h> |
99 | | #include <LibWeb/SVG/SVGMetadataElement.h> |
100 | | #include <LibWeb/SVG/SVGPathElement.h> |
101 | | #include <LibWeb/SVG/SVGPolygonElement.h> |
102 | | #include <LibWeb/SVG/SVGPolylineElement.h> |
103 | | #include <LibWeb/SVG/SVGRadialGradientElement.h> |
104 | | #include <LibWeb/SVG/SVGRectElement.h> |
105 | | #include <LibWeb/SVG/SVGSVGElement.h> |
106 | | #include <LibWeb/SVG/SVGScriptElement.h> |
107 | | #include <LibWeb/SVG/SVGStopElement.h> |
108 | | #include <LibWeb/SVG/SVGStyleElement.h> |
109 | | #include <LibWeb/SVG/SVGSymbolElement.h> |
110 | | #include <LibWeb/SVG/SVGTSpanElement.h> |
111 | | #include <LibWeb/SVG/SVGTextElement.h> |
112 | | #include <LibWeb/SVG/SVGTextPathElement.h> |
113 | | #include <LibWeb/SVG/SVGTitleElement.h> |
114 | | #include <LibWeb/SVG/SVGUseElement.h> |
115 | | #include <LibWeb/SVG/TagNames.h> |
116 | | #include <LibWeb/WebIDL/AbstractOperations.h> |
117 | | |
118 | | namespace Web::DOM { |
119 | | |
120 | | ErrorOr<FixedArray<FlyString>> valid_local_names_for_given_html_element_interface(StringView html_element_interface_name) |
121 | 0 | { |
122 | 0 | if (html_element_interface_name == "HTMLAnchorElement"sv) |
123 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::a }); |
124 | 0 | if (html_element_interface_name == "HTMLAreaElement"sv) |
125 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::area }); |
126 | 0 | if (html_element_interface_name == "HTMLAudioElement"sv) |
127 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::audio }); |
128 | 0 | if (html_element_interface_name == "HTMLBaseElement"sv) |
129 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::base }); |
130 | 0 | if (html_element_interface_name == "HTMLBodyElement"sv) |
131 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::body }); |
132 | 0 | if (html_element_interface_name == "HTMLBRElement"sv) |
133 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::br }); |
134 | 0 | if (html_element_interface_name == "HTMLButtonElement"sv) |
135 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::button }); |
136 | 0 | if (html_element_interface_name == "HTMLCanvasElement"sv) |
137 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::canvas }); |
138 | 0 | if (html_element_interface_name == "HTMLDataElement"sv) |
139 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::data }); |
140 | 0 | if (html_element_interface_name == "HTMLDataListElement"sv) |
141 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::datalist }); |
142 | 0 | if (html_element_interface_name == "HTMLDetailsElement"sv) |
143 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::details }); |
144 | 0 | if (html_element_interface_name == "HTMLDialogElement"sv) |
145 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::dialog }); |
146 | 0 | if (html_element_interface_name == "HTMLDirectoryElement"sv) |
147 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::dir }); |
148 | 0 | if (html_element_interface_name == "HTMLDivElement"sv) |
149 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::div }); |
150 | 0 | if (html_element_interface_name == "HTMLDListElement"sv) |
151 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::dl }); |
152 | 0 | if (html_element_interface_name == "HTMLEmbedElement"sv) |
153 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::embed }); |
154 | 0 | if (html_element_interface_name == "HTMLFieldSetElement"sv) |
155 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::fieldset }); |
156 | 0 | if (html_element_interface_name == "HTMLFontElement"sv) |
157 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::font }); |
158 | 0 | if (html_element_interface_name == "HTMLFormElement"sv) |
159 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::form }); |
160 | 0 | if (html_element_interface_name == "HTMLFrameElement"sv) |
161 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::frame }); |
162 | 0 | if (html_element_interface_name == "HTMLFrameSetElement"sv) |
163 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::frameset }); |
164 | 0 | if (html_element_interface_name == "HTMLHeadElement"sv) |
165 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::head }); |
166 | 0 | if (html_element_interface_name == "HTMLHeadingElement"sv) |
167 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6 }); |
168 | 0 | if (html_element_interface_name == "HTMLHRElement"sv) |
169 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::hr }); |
170 | 0 | if (html_element_interface_name == "HTMLHtmlElement"sv) |
171 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::html }); |
172 | 0 | if (html_element_interface_name == "HTMLIFrameElement"sv) |
173 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::iframe }); |
174 | 0 | if (html_element_interface_name == "HTMLImageElement"sv) |
175 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::img }); |
176 | 0 | if (html_element_interface_name == "HTMLInputElement"sv) |
177 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::input }); |
178 | 0 | if (html_element_interface_name == "HTMLLabelElement"sv) |
179 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::label }); |
180 | 0 | if (html_element_interface_name == "HTMLLIElement"sv) |
181 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::li }); |
182 | 0 | if (html_element_interface_name == "HTMLLinkElement"sv) |
183 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::link }); |
184 | 0 | if (html_element_interface_name == "HTMLMapElement"sv) |
185 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::map }); |
186 | 0 | if (html_element_interface_name == "HTMLMarqueeElement"sv) |
187 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::marquee }); |
188 | 0 | if (html_element_interface_name == "HTMLMenuElement"sv) |
189 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::menu }); |
190 | 0 | if (html_element_interface_name == "HTMLMetaElement"sv) |
191 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::meta }); |
192 | 0 | if (html_element_interface_name == "HTMLMeterElement"sv) |
193 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::meter }); |
194 | 0 | if (html_element_interface_name == "HTMLModElement"sv) |
195 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::ins, HTML::TagNames::del }); |
196 | 0 | if (html_element_interface_name == "HTMLOListElement"sv) |
197 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::ol }); |
198 | 0 | if (html_element_interface_name == "HTMLObjectElement"sv) |
199 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::object }); |
200 | 0 | if (html_element_interface_name == "HTMLOptGroupElement"sv) |
201 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::optgroup }); |
202 | 0 | if (html_element_interface_name == "HTMLOutputElement"sv) |
203 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::output }); |
204 | 0 | if (html_element_interface_name == "HTMLParagraphElement"sv) |
205 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::p }); |
206 | 0 | if (html_element_interface_name == "HTMLParamElement"sv) |
207 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::param }); |
208 | 0 | if (html_element_interface_name == "HTMLPictureElement"sv) |
209 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::picture }); |
210 | 0 | if (html_element_interface_name == "HTMLPreElement"sv) |
211 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::pre, HTML::TagNames::listing, HTML::TagNames::xmp }); |
212 | 0 | if (html_element_interface_name == "HTMLProgressElement"sv) |
213 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::progress }); |
214 | 0 | if (html_element_interface_name == "HTMLQuoteElement"sv) |
215 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::blockquote, HTML::TagNames::q }); |
216 | 0 | if (html_element_interface_name == "HTMLScriptElement"sv) |
217 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::script }); |
218 | 0 | if (html_element_interface_name == "HTMLSelectElement"sv) |
219 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::select }); |
220 | 0 | if (html_element_interface_name == "HTMLSlotElement"sv) |
221 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::slot }); |
222 | 0 | if (html_element_interface_name == "HTMLSourceElement"sv) |
223 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::source }); |
224 | 0 | if (html_element_interface_name == "HTMLSpanElement"sv) |
225 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::span }); |
226 | 0 | if (html_element_interface_name == "HTMLStyleElement"sv) |
227 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::style }); |
228 | 0 | if (html_element_interface_name == "HTMLTableCaptionElement"sv) |
229 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::caption }); |
230 | 0 | if (html_element_interface_name == "HTMLTableCellElement"sv) |
231 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::td, HTML::TagNames::th }); |
232 | 0 | if (html_element_interface_name == "HTMLTableColElement"sv) |
233 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::colgroup, HTML::TagNames::col }); |
234 | 0 | if (html_element_interface_name == "HTMLTableElement"sv) |
235 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::table }); |
236 | 0 | if (html_element_interface_name == "HTMLTableSectionElement"sv) |
237 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::tbody, HTML::TagNames::thead, HTML::TagNames::tfoot }); |
238 | 0 | if (html_element_interface_name == "HTMLTemplateElement"sv) |
239 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::template_ }); |
240 | 0 | if (html_element_interface_name == "HTMLTextAreaElement"sv) |
241 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::textarea }); |
242 | 0 | if (html_element_interface_name == "HTMLTimeElement"sv) |
243 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::time }); |
244 | 0 | if (html_element_interface_name == "HTMLTitleElement"sv) |
245 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::title }); |
246 | 0 | if (html_element_interface_name == "HTMLTrackElement"sv) |
247 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::track }); |
248 | 0 | if (html_element_interface_name == "HTMLUListElement"sv) |
249 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::ul }); |
250 | 0 | if (html_element_interface_name == "HTMLVideoElement"sv) |
251 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::video }); |
252 | 0 | if (html_element_interface_name == "HTMLElement"sv) |
253 | 0 | return FixedArray<FlyString>::create({ HTML::TagNames::article, HTML::TagNames::section, HTML::TagNames::nav, HTML::TagNames::aside, HTML::TagNames::hgroup, HTML::TagNames::header, HTML::TagNames::footer, HTML::TagNames::address, HTML::TagNames::dt, HTML::TagNames::dd, HTML::TagNames::figure, HTML::TagNames::figcaption, HTML::TagNames::main, HTML::TagNames::em, HTML::TagNames::strong, HTML::TagNames::small, HTML::TagNames::s, HTML::TagNames::cite, HTML::TagNames::dfn, HTML::TagNames::abbr, HTML::TagNames::ruby, HTML::TagNames::rt, HTML::TagNames::rp, HTML::TagNames::code, HTML::TagNames::var, HTML::TagNames::samp, HTML::TagNames::kbd, HTML::TagNames::sub, HTML::TagNames::sup, HTML::TagNames::i, HTML::TagNames::b, HTML::TagNames::u, HTML::TagNames::mark, HTML::TagNames::bdi, HTML::TagNames::bdo, HTML::TagNames::wbr, HTML::TagNames::summary, HTML::TagNames::noscript, HTML::TagNames::acronym, HTML::TagNames::basefont, HTML::TagNames::big, HTML::TagNames::center, HTML::TagNames::nobr, HTML::TagNames::noembed, HTML::TagNames::noframes, HTML::TagNames::plaintext, HTML::TagNames::rb, HTML::TagNames::rtc, HTML::TagNames::strike, HTML::TagNames::tt }); |
254 | 0 | return FixedArray<FlyString>::create({}); |
255 | 0 | } |
256 | | |
257 | | // https://html.spec.whatwg.org/multipage/dom.html#elements-in-the-dom%3Aelement-interface |
258 | | bool is_unknown_html_element(FlyString const& tag_name) |
259 | 0 | { |
260 | | // NOTE: This is intentionally case-sensitive. |
261 | | |
262 | | // 1. If name is applet, bgsound, blink, isindex, keygen, multicol, nextid, or spacer, then return HTMLUnknownElement. |
263 | 0 | if (tag_name.is_one_of(HTML::TagNames::applet, HTML::TagNames::bgsound, HTML::TagNames::blink, HTML::TagNames::isindex, HTML::TagNames::keygen, HTML::TagNames::multicol, HTML::TagNames::nextid, HTML::TagNames::spacer)) |
264 | 0 | return true; |
265 | | |
266 | | // 2. If name is acronym, basefont, big, center, nobr, noembed, noframes, plaintext, rb, rtc, strike, or tt, then return HTMLElement. |
267 | | // 3. If name is listing or xmp, then return HTMLPreElement. |
268 | | // 4. Otherwise, if this specification defines an interface appropriate for the element type corresponding to the local name name, then return that interface. |
269 | | // 5. If other applicable specifications define an appropriate interface for name, then return the interface they define. |
270 | 0 | #define __ENUMERATE_HTML_TAG(name) \ |
271 | 0 | if (tag_name == HTML::TagNames::name) \ |
272 | 0 | return false; |
273 | 0 | ENUMERATE_HTML_TAGS |
274 | 0 | #undef __ENUMERATE_HTML_TAG |
275 | | |
276 | | // 6. If name is a valid custom element name, then return HTMLElement. |
277 | 0 | if (HTML::is_valid_custom_element_name(tag_name)) |
278 | 0 | return false; |
279 | | |
280 | | // 7. Return HTMLUnknownElement. |
281 | 0 | return true; |
282 | 0 | } |
283 | | |
284 | | // https://html.spec.whatwg.org/#elements-in-the-dom:element-interface |
285 | | static JS::NonnullGCPtr<Element> create_html_element(JS::Realm& realm, Document& document, QualifiedName qualified_name) |
286 | 0 | { |
287 | 0 | FlyString tag_name = qualified_name.local_name(); |
288 | |
|
289 | 0 | if (tag_name == HTML::TagNames::a) |
290 | 0 | return realm.heap().allocate<HTML::HTMLAnchorElement>(realm, document, move(qualified_name)); |
291 | 0 | if (tag_name == HTML::TagNames::area) |
292 | 0 | return realm.heap().allocate<HTML::HTMLAreaElement>(realm, document, move(qualified_name)); |
293 | 0 | if (tag_name == HTML::TagNames::audio) |
294 | 0 | return realm.heap().allocate<HTML::HTMLAudioElement>(realm, document, move(qualified_name)); |
295 | 0 | if (tag_name == HTML::TagNames::base) |
296 | 0 | return realm.heap().allocate<HTML::HTMLBaseElement>(realm, document, move(qualified_name)); |
297 | 0 | if (tag_name == HTML::TagNames::body) |
298 | 0 | return realm.heap().allocate<HTML::HTMLBodyElement>(realm, document, move(qualified_name)); |
299 | 0 | if (tag_name == HTML::TagNames::br) |
300 | 0 | return realm.heap().allocate<HTML::HTMLBRElement>(realm, document, move(qualified_name)); |
301 | 0 | if (tag_name == HTML::TagNames::button) |
302 | 0 | return realm.heap().allocate<HTML::HTMLButtonElement>(realm, document, move(qualified_name)); |
303 | 0 | if (tag_name == HTML::TagNames::canvas) |
304 | 0 | return realm.heap().allocate<HTML::HTMLCanvasElement>(realm, document, move(qualified_name)); |
305 | 0 | if (tag_name == HTML::TagNames::data) |
306 | 0 | return realm.heap().allocate<HTML::HTMLDataElement>(realm, document, move(qualified_name)); |
307 | 0 | if (tag_name == HTML::TagNames::datalist) |
308 | 0 | return realm.heap().allocate<HTML::HTMLDataListElement>(realm, document, move(qualified_name)); |
309 | 0 | if (tag_name == HTML::TagNames::details) |
310 | 0 | return realm.heap().allocate<HTML::HTMLDetailsElement>(realm, document, move(qualified_name)); |
311 | 0 | if (tag_name == HTML::TagNames::dialog) |
312 | 0 | return realm.heap().allocate<HTML::HTMLDialogElement>(realm, document, move(qualified_name)); |
313 | 0 | if (tag_name == HTML::TagNames::dir) |
314 | 0 | return realm.heap().allocate<HTML::HTMLDirectoryElement>(realm, document, move(qualified_name)); |
315 | 0 | if (tag_name == HTML::TagNames::div) |
316 | 0 | return realm.heap().allocate<HTML::HTMLDivElement>(realm, document, move(qualified_name)); |
317 | 0 | if (tag_name == HTML::TagNames::dl) |
318 | 0 | return realm.heap().allocate<HTML::HTMLDListElement>(realm, document, move(qualified_name)); |
319 | 0 | if (tag_name == HTML::TagNames::embed) |
320 | 0 | return realm.heap().allocate<HTML::HTMLEmbedElement>(realm, document, move(qualified_name)); |
321 | 0 | if (tag_name == HTML::TagNames::fieldset) |
322 | 0 | return realm.heap().allocate<HTML::HTMLFieldSetElement>(realm, document, move(qualified_name)); |
323 | 0 | if (tag_name == HTML::TagNames::font) |
324 | 0 | return realm.heap().allocate<HTML::HTMLFontElement>(realm, document, move(qualified_name)); |
325 | 0 | if (tag_name == HTML::TagNames::form) |
326 | 0 | return realm.heap().allocate<HTML::HTMLFormElement>(realm, document, move(qualified_name)); |
327 | 0 | if (tag_name == HTML::TagNames::frame) |
328 | 0 | return realm.heap().allocate<HTML::HTMLFrameElement>(realm, document, move(qualified_name)); |
329 | 0 | if (tag_name == HTML::TagNames::frameset) |
330 | 0 | return realm.heap().allocate<HTML::HTMLFrameSetElement>(realm, document, move(qualified_name)); |
331 | 0 | if (tag_name == HTML::TagNames::head) |
332 | 0 | return realm.heap().allocate<HTML::HTMLHeadElement>(realm, document, move(qualified_name)); |
333 | 0 | if (tag_name.is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6)) |
334 | 0 | return realm.heap().allocate<HTML::HTMLHeadingElement>(realm, document, move(qualified_name)); |
335 | 0 | if (tag_name == HTML::TagNames::hr) |
336 | 0 | return realm.heap().allocate<HTML::HTMLHRElement>(realm, document, move(qualified_name)); |
337 | 0 | if (tag_name == HTML::TagNames::html) |
338 | 0 | return realm.heap().allocate<HTML::HTMLHtmlElement>(realm, document, move(qualified_name)); |
339 | 0 | if (tag_name == HTML::TagNames::iframe) |
340 | 0 | return realm.heap().allocate<HTML::HTMLIFrameElement>(realm, document, move(qualified_name)); |
341 | 0 | if (tag_name == HTML::TagNames::img) |
342 | 0 | return realm.heap().allocate<HTML::HTMLImageElement>(realm, document, move(qualified_name)); |
343 | 0 | if (tag_name == HTML::TagNames::input) |
344 | 0 | return realm.heap().allocate<HTML::HTMLInputElement>(realm, document, move(qualified_name)); |
345 | 0 | if (tag_name == HTML::TagNames::label) |
346 | 0 | return realm.heap().allocate<HTML::HTMLLabelElement>(realm, document, move(qualified_name)); |
347 | 0 | if (tag_name == HTML::TagNames::legend) |
348 | 0 | return realm.heap().allocate<HTML::HTMLLegendElement>(realm, document, move(qualified_name)); |
349 | 0 | if (tag_name == HTML::TagNames::li) |
350 | 0 | return realm.heap().allocate<HTML::HTMLLIElement>(realm, document, move(qualified_name)); |
351 | 0 | if (tag_name == HTML::TagNames::link) |
352 | 0 | return realm.heap().allocate<HTML::HTMLLinkElement>(realm, document, move(qualified_name)); |
353 | 0 | if (tag_name == HTML::TagNames::map) |
354 | 0 | return realm.heap().allocate<HTML::HTMLMapElement>(realm, document, move(qualified_name)); |
355 | 0 | if (tag_name == HTML::TagNames::marquee) |
356 | 0 | return realm.heap().allocate<HTML::HTMLMarqueeElement>(realm, document, move(qualified_name)); |
357 | 0 | if (tag_name == HTML::TagNames::menu) |
358 | 0 | return realm.heap().allocate<HTML::HTMLMenuElement>(realm, document, move(qualified_name)); |
359 | 0 | if (tag_name == HTML::TagNames::meta) |
360 | 0 | return realm.heap().allocate<HTML::HTMLMetaElement>(realm, document, move(qualified_name)); |
361 | 0 | if (tag_name == HTML::TagNames::meter) |
362 | 0 | return realm.heap().allocate<HTML::HTMLMeterElement>(realm, document, move(qualified_name)); |
363 | 0 | if (tag_name.is_one_of(HTML::TagNames::ins, HTML::TagNames::del)) |
364 | 0 | return realm.heap().allocate<HTML::HTMLModElement>(realm, document, move(qualified_name)); |
365 | 0 | if (tag_name == HTML::TagNames::object) |
366 | 0 | return realm.heap().allocate<HTML::HTMLObjectElement>(realm, document, move(qualified_name)); |
367 | 0 | if (tag_name == HTML::TagNames::ol) |
368 | 0 | return realm.heap().allocate<HTML::HTMLOListElement>(realm, document, move(qualified_name)); |
369 | 0 | if (tag_name == HTML::TagNames::optgroup) |
370 | 0 | return realm.heap().allocate<HTML::HTMLOptGroupElement>(realm, document, move(qualified_name)); |
371 | 0 | if (tag_name == HTML::TagNames::option) |
372 | 0 | return realm.heap().allocate<HTML::HTMLOptionElement>(realm, document, move(qualified_name)); |
373 | 0 | if (tag_name == HTML::TagNames::output) |
374 | 0 | return realm.heap().allocate<HTML::HTMLOutputElement>(realm, document, move(qualified_name)); |
375 | 0 | if (tag_name == HTML::TagNames::p) |
376 | 0 | return realm.heap().allocate<HTML::HTMLParagraphElement>(realm, document, move(qualified_name)); |
377 | 0 | if (tag_name == HTML::TagNames::param) |
378 | 0 | return realm.heap().allocate<HTML::HTMLParamElement>(realm, document, move(qualified_name)); |
379 | 0 | if (tag_name == HTML::TagNames::picture) |
380 | 0 | return realm.heap().allocate<HTML::HTMLPictureElement>(realm, document, move(qualified_name)); |
381 | | // NOTE: The obsolete elements "listing" and "xmp" are explicitly mapped to HTMLPreElement in the specification. |
382 | 0 | if (tag_name.is_one_of(HTML::TagNames::pre, HTML::TagNames::listing, HTML::TagNames::xmp)) |
383 | 0 | return realm.heap().allocate<HTML::HTMLPreElement>(realm, document, move(qualified_name)); |
384 | 0 | if (tag_name == HTML::TagNames::progress) |
385 | 0 | return realm.heap().allocate<HTML::HTMLProgressElement>(realm, document, move(qualified_name)); |
386 | 0 | if (tag_name.is_one_of(HTML::TagNames::blockquote, HTML::TagNames::q)) |
387 | 0 | return realm.heap().allocate<HTML::HTMLQuoteElement>(realm, document, move(qualified_name)); |
388 | 0 | if (tag_name == HTML::TagNames::script) |
389 | 0 | return realm.heap().allocate<HTML::HTMLScriptElement>(realm, document, move(qualified_name)); |
390 | 0 | if (tag_name == HTML::TagNames::select) |
391 | 0 | return realm.heap().allocate<HTML::HTMLSelectElement>(realm, document, move(qualified_name)); |
392 | 0 | if (tag_name == HTML::TagNames::slot) |
393 | 0 | return realm.heap().allocate<HTML::HTMLSlotElement>(realm, document, move(qualified_name)); |
394 | 0 | if (tag_name == HTML::TagNames::source) |
395 | 0 | return realm.heap().allocate<HTML::HTMLSourceElement>(realm, document, move(qualified_name)); |
396 | 0 | if (tag_name == HTML::TagNames::span) |
397 | 0 | return realm.heap().allocate<HTML::HTMLSpanElement>(realm, document, move(qualified_name)); |
398 | 0 | if (tag_name == HTML::TagNames::style) |
399 | 0 | return realm.heap().allocate<HTML::HTMLStyleElement>(realm, document, move(qualified_name)); |
400 | 0 | if (tag_name == HTML::TagNames::summary) |
401 | 0 | return realm.heap().allocate<HTML::HTMLSummaryElement>(realm, document, move(qualified_name)); |
402 | 0 | if (tag_name == HTML::TagNames::caption) |
403 | 0 | return realm.heap().allocate<HTML::HTMLTableCaptionElement>(realm, document, move(qualified_name)); |
404 | 0 | if (tag_name.is_one_of(Web::HTML::TagNames::td, Web::HTML::TagNames::th)) |
405 | 0 | return realm.heap().allocate<HTML::HTMLTableCellElement>(realm, document, move(qualified_name)); |
406 | 0 | if (tag_name.is_one_of(HTML::TagNames::colgroup, HTML::TagNames::col)) |
407 | 0 | return realm.heap().allocate<HTML::HTMLTableColElement>(realm, document, move(qualified_name)); |
408 | 0 | if (tag_name == HTML::TagNames::table) |
409 | 0 | return realm.heap().allocate<HTML::HTMLTableElement>(realm, document, move(qualified_name)); |
410 | 0 | if (tag_name == HTML::TagNames::tr) |
411 | 0 | return realm.heap().allocate<HTML::HTMLTableRowElement>(realm, document, move(qualified_name)); |
412 | 0 | if (tag_name.is_one_of(HTML::TagNames::tbody, HTML::TagNames::thead, HTML::TagNames::tfoot)) |
413 | 0 | return realm.heap().allocate<HTML::HTMLTableSectionElement>(realm, document, move(qualified_name)); |
414 | 0 | if (tag_name == HTML::TagNames::template_) |
415 | 0 | return realm.heap().allocate<HTML::HTMLTemplateElement>(realm, document, move(qualified_name)); |
416 | 0 | if (tag_name == HTML::TagNames::textarea) |
417 | 0 | return realm.heap().allocate<HTML::HTMLTextAreaElement>(realm, document, move(qualified_name)); |
418 | 0 | if (tag_name == HTML::TagNames::time) |
419 | 0 | return realm.heap().allocate<HTML::HTMLTimeElement>(realm, document, move(qualified_name)); |
420 | 0 | if (tag_name == HTML::TagNames::title) |
421 | 0 | return realm.heap().allocate<HTML::HTMLTitleElement>(realm, document, move(qualified_name)); |
422 | 0 | if (tag_name == HTML::TagNames::track) |
423 | 0 | return realm.heap().allocate<HTML::HTMLTrackElement>(realm, document, move(qualified_name)); |
424 | 0 | if (tag_name == HTML::TagNames::ul) |
425 | 0 | return realm.heap().allocate<HTML::HTMLUListElement>(realm, document, move(qualified_name)); |
426 | 0 | if (tag_name == HTML::TagNames::video) |
427 | 0 | return realm.heap().allocate<HTML::HTMLVideoElement>(realm, document, move(qualified_name)); |
428 | 0 | if (tag_name.is_one_of( |
429 | 0 | HTML::TagNames::article, HTML::TagNames::section, HTML::TagNames::nav, HTML::TagNames::aside, HTML::TagNames::hgroup, HTML::TagNames::header, HTML::TagNames::footer, HTML::TagNames::address, HTML::TagNames::dt, HTML::TagNames::dd, HTML::TagNames::figure, HTML::TagNames::figcaption, HTML::TagNames::main, HTML::TagNames::em, HTML::TagNames::strong, HTML::TagNames::small, HTML::TagNames::s, HTML::TagNames::cite, HTML::TagNames::dfn, HTML::TagNames::abbr, HTML::TagNames::ruby, HTML::TagNames::rt, HTML::TagNames::rp, HTML::TagNames::code, HTML::TagNames::var, HTML::TagNames::samp, HTML::TagNames::kbd, HTML::TagNames::sub, HTML::TagNames::sup, HTML::TagNames::i, HTML::TagNames::b, HTML::TagNames::u, HTML::TagNames::mark, HTML::TagNames::bdi, HTML::TagNames::bdo, HTML::TagNames::wbr, HTML::TagNames::noscript, |
430 | | // Obsolete |
431 | 0 | HTML::TagNames::acronym, HTML::TagNames::basefont, HTML::TagNames::big, HTML::TagNames::center, HTML::TagNames::nobr, HTML::TagNames::noembed, HTML::TagNames::noframes, HTML::TagNames::plaintext, HTML::TagNames::rb, HTML::TagNames::rtc, HTML::TagNames::strike, HTML::TagNames::tt)) |
432 | 0 | return realm.heap().allocate<HTML::HTMLElement>(realm, document, move(qualified_name)); |
433 | 0 | if (HTML::is_valid_custom_element_name(qualified_name.local_name())) |
434 | 0 | return realm.heap().allocate<HTML::HTMLElement>(realm, document, move(qualified_name)); |
435 | | |
436 | 0 | return realm.heap().allocate<HTML::HTMLUnknownElement>(realm, document, move(qualified_name)); |
437 | 0 | } |
438 | | |
439 | | static JS::NonnullGCPtr<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& document, QualifiedName qualified_name) |
440 | 0 | { |
441 | 0 | auto const& local_name = qualified_name.local_name(); |
442 | |
|
443 | 0 | if (local_name == SVG::TagNames::svg) |
444 | 0 | return realm.heap().allocate<SVG::SVGSVGElement>(realm, document, move(qualified_name)); |
445 | | // FIXME: Support SVG's mixedCase tag names properly. |
446 | 0 | if (local_name.equals_ignoring_ascii_case(SVG::TagNames::clipPath)) |
447 | 0 | return realm.heap().allocate<SVG::SVGClipPathElement>(realm, document, move(qualified_name)); |
448 | 0 | if (local_name == SVG::TagNames::circle) |
449 | 0 | return realm.heap().allocate<SVG::SVGCircleElement>(realm, document, move(qualified_name)); |
450 | 0 | if (local_name.equals_ignoring_ascii_case(SVG::TagNames::defs)) |
451 | 0 | return realm.heap().allocate<SVG::SVGDefsElement>(realm, document, move(qualified_name)); |
452 | 0 | if (local_name == SVG::TagNames::desc) |
453 | 0 | return realm.heap().allocate<SVG::SVGDescElement>(realm, document, move(qualified_name)); |
454 | 0 | if (local_name == SVG::TagNames::ellipse) |
455 | 0 | return realm.heap().allocate<SVG::SVGEllipseElement>(realm, document, move(qualified_name)); |
456 | 0 | if (local_name.equals_ignoring_ascii_case(SVG::TagNames::foreignObject)) |
457 | 0 | return realm.heap().allocate<SVG::SVGForeignObjectElement>(realm, document, move(qualified_name)); |
458 | 0 | if (local_name == SVG::TagNames::line) |
459 | 0 | return realm.heap().allocate<SVG::SVGLineElement>(realm, document, move(qualified_name)); |
460 | 0 | if (local_name == SVG::TagNames::linearGradient) |
461 | 0 | return realm.heap().allocate<SVG::SVGLinearGradientElement>(realm, document, move(qualified_name)); |
462 | 0 | if (local_name == SVG::TagNames::mask) |
463 | 0 | return realm.heap().allocate<SVG::SVGMaskElement>(realm, document, move(qualified_name)); |
464 | 0 | if (local_name == SVG::TagNames::metadata) |
465 | 0 | return realm.heap().allocate<SVG::SVGMetadataElement>(realm, document, move(qualified_name)); |
466 | 0 | if (local_name == SVG::TagNames::path) |
467 | 0 | return realm.heap().allocate<SVG::SVGPathElement>(realm, document, move(qualified_name)); |
468 | 0 | if (local_name == SVG::TagNames::polygon) |
469 | 0 | return realm.heap().allocate<SVG::SVGPolygonElement>(realm, document, move(qualified_name)); |
470 | 0 | if (local_name == SVG::TagNames::polyline) |
471 | 0 | return realm.heap().allocate<SVG::SVGPolylineElement>(realm, document, move(qualified_name)); |
472 | 0 | if (local_name == SVG::TagNames::radialGradient) |
473 | 0 | return realm.heap().allocate<SVG::SVGRadialGradientElement>(realm, document, move(qualified_name)); |
474 | 0 | if (local_name == SVG::TagNames::rect) |
475 | 0 | return realm.heap().allocate<SVG::SVGRectElement>(realm, document, move(qualified_name)); |
476 | 0 | if (local_name == SVG::TagNames::g) |
477 | 0 | return realm.heap().allocate<SVG::SVGGElement>(realm, document, move(qualified_name)); |
478 | 0 | if (local_name == SVG::TagNames::stop) |
479 | 0 | return realm.heap().allocate<SVG::SVGStopElement>(realm, document, move(qualified_name)); |
480 | 0 | if (local_name == SVG::TagNames::style) |
481 | 0 | return realm.heap().allocate<SVG::SVGStyleElement>(realm, document, move(qualified_name)); |
482 | 0 | if (local_name == SVG::TagNames::symbol) |
483 | 0 | return realm.heap().allocate<SVG::SVGSymbolElement>(realm, document, move(qualified_name)); |
484 | 0 | if (local_name == SVG::TagNames::text) |
485 | 0 | return realm.heap().allocate<SVG::SVGTextElement>(realm, document, move(qualified_name)); |
486 | 0 | if (local_name == SVG::TagNames::textPath) |
487 | 0 | return realm.heap().allocate<SVG::SVGTextPathElement>(realm, document, move(qualified_name)); |
488 | 0 | if (local_name == SVG::TagNames::title) |
489 | 0 | return realm.heap().allocate<SVG::SVGTitleElement>(realm, document, move(qualified_name)); |
490 | 0 | if (local_name == SVG::TagNames::tspan) |
491 | 0 | return realm.heap().allocate<SVG::SVGTSpanElement>(realm, document, move(qualified_name)); |
492 | 0 | if (local_name == SVG::TagNames::use) |
493 | 0 | return realm.heap().allocate<SVG::SVGUseElement>(realm, document, move(qualified_name)); |
494 | 0 | if (local_name == SVG::TagNames::script) |
495 | 0 | return realm.heap().allocate<SVG::SVGScriptElement>(realm, document, move(qualified_name)); |
496 | 0 | if (local_name == SVG::TagNames::a) |
497 | 0 | return realm.heap().allocate<SVG::SVGAElement>(realm, document, move(qualified_name)); |
498 | 0 | if (local_name == SVG::TagNames::image) |
499 | 0 | return realm.heap().allocate<SVG::SVGImageElement>(realm, document, move(qualified_name)); |
500 | | |
501 | | // https://svgwg.org/svg2-draft/types.html#ElementsInTheSVGDOM |
502 | | // Elements in the SVG namespace whose local name does not match an element defined in any |
503 | | // specification supported by the software must nonetheless implement the SVGElement interface. |
504 | 0 | return realm.heap().allocate<SVG::SVGElement>(realm, document, move(qualified_name)); |
505 | 0 | } |
506 | | |
507 | | static JS::NonnullGCPtr<MathML::MathMLElement> create_mathml_element(JS::Realm& realm, Document& document, QualifiedName qualified_name) |
508 | 0 | { |
509 | | // https://w3c.github.io/mathml-core/#dom-and-javascript |
510 | | // All the nodes representing MathML elements in the DOM must implement, and expose to scripts, |
511 | | // the following MathMLElement interface. |
512 | | |
513 | | // https://w3c.github.io/mathml-core/#mathml-elements-and-attributes |
514 | | // The term MathML element refers to any element in the MathML namespace. |
515 | |
|
516 | 0 | return realm.heap().allocate<MathML::MathMLElement>(realm, document, move(qualified_name)); |
517 | 0 | } |
518 | | // https://dom.spec.whatwg.org/#concept-create-element |
519 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> create_element(Document& document, FlyString local_name, Optional<FlyString> namespace_, Optional<FlyString> prefix, Optional<String> is_value, bool synchronous_custom_elements_flag) |
520 | 0 | { |
521 | 0 | auto& realm = document.realm(); |
522 | | |
523 | | // 1. If prefix was not given, let prefix be null. |
524 | | // NOTE: This is already taken care of by `prefix` having a default value. |
525 | | |
526 | | // 2. If is was not given, let is be null. |
527 | | // NOTE: This is already taken care of by `is` having a default value. |
528 | | |
529 | | // 3. Let result be null. |
530 | | // NOTE: We collapse this into just returning an element where necessary. |
531 | | |
532 | | // 4. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is. |
533 | 0 | auto definition = document.lookup_custom_element_definition(namespace_, local_name, is_value); |
534 | | |
535 | | // 5. If definition is non-null, and definition’s name is not equal to its local name (i.e., definition represents a customized built-in element), then: |
536 | 0 | if (definition && definition->name() != definition->local_name()) { |
537 | | // 1. Let interface be the element interface for localName and the HTML namespace. |
538 | | // 2. Set result to a new element that implements interface, with no attributes, namespace set to the HTML namespace, |
539 | | // namespace prefix set to prefix, local name set to localName, custom element state set to "undefined", custom element definition set to null, |
540 | | // is value set to is, and node document set to document. |
541 | 0 | auto element = create_html_element(realm, document, QualifiedName { local_name, prefix, Namespace::HTML }); |
542 | | |
543 | | // 3. If the synchronous custom elements flag is set, then run this step while catching any exceptions: |
544 | 0 | if (synchronous_custom_elements_flag) { |
545 | | // 1. Upgrade element using definition. |
546 | 0 | auto upgrade_result = element->upgrade_element(*definition); |
547 | | |
548 | | // If this step threw an exception, then: |
549 | 0 | if (upgrade_result.is_throw_completion()) { |
550 | | // 1. Report the exception. |
551 | 0 | HTML::report_exception(upgrade_result, realm); |
552 | | |
553 | | // 2. Set result’s custom element state to "failed". |
554 | 0 | element->set_custom_element_state(CustomElementState::Failed); |
555 | 0 | } |
556 | 0 | } |
557 | | |
558 | | // 4. Otherwise, enqueue a custom element upgrade reaction given result and definition. |
559 | 0 | else { |
560 | 0 | element->enqueue_a_custom_element_upgrade_reaction(*definition); |
561 | 0 | } |
562 | |
|
563 | 0 | return element; |
564 | 0 | } |
565 | | |
566 | | // 6. Otherwise, if definition is non-null, then: |
567 | 0 | if (definition) { |
568 | | // 1. If the synchronous custom elements flag is set, then run these steps while catching any exceptions: |
569 | 0 | if (synchronous_custom_elements_flag) { |
570 | 0 | auto synchronously_upgrade_custom_element = [&]() -> JS::ThrowCompletionOr<JS::NonnullGCPtr<HTML::HTMLElement>> { |
571 | 0 | auto& vm = document.vm(); |
572 | | |
573 | | // 1. Let C be definition’s constructor. |
574 | 0 | auto& constructor = definition->constructor(); |
575 | | |
576 | | // 2. Set result to the result of constructing C, with no arguments. |
577 | 0 | auto result = TRY(WebIDL::construct(constructor)); |
578 | | |
579 | | // FIXME: 3. Assert: result’s custom element state and custom element definition are initialized. |
580 | | // FIXME: 4. Assert: result’s namespace is the HTML namespace. |
581 | | // Spec Note: IDL enforces that result is an HTMLElement object, which all use the HTML namespace. |
582 | | // IDL does not currently convert the object for us, so we will have to do it here. |
583 | |
|
584 | 0 | if (!result.has_value() || !result->is_object() || !is<HTML::HTMLElement>(result->as_object())) |
585 | 0 | return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "HTMLElement"sv); |
586 | | |
587 | 0 | JS::NonnullGCPtr<HTML::HTMLElement> element = verify_cast<HTML::HTMLElement>(result->as_object()); |
588 | | |
589 | | // 5. If result’s attribute list is not empty, then throw a "NotSupportedError" DOMException. |
590 | 0 | if (element->has_attributes()) |
591 | 0 | return JS::throw_completion(WebIDL::NotSupportedError::create(realm, "Synchronously created custom element cannot have attributes"_string)); |
592 | | |
593 | | // 6. If result has children, then throw a "NotSupportedError" DOMException. |
594 | 0 | if (element->has_children()) |
595 | 0 | return JS::throw_completion(WebIDL::NotSupportedError::create(realm, "Synchronously created custom element cannot have children"_string)); |
596 | | |
597 | | // 7. If result’s parent is not null, then throw a "NotSupportedError" DOMException. |
598 | 0 | if (element->parent()) |
599 | 0 | return JS::throw_completion(WebIDL::NotSupportedError::create(realm, "Synchronously created custom element cannot have a parent"_string)); |
600 | | |
601 | | // 8. If result’s node document is not document, then throw a "NotSupportedError" DOMException. |
602 | 0 | if (&element->document() != &document) |
603 | 0 | return JS::throw_completion(WebIDL::NotSupportedError::create(realm, "Synchronously created custom element must be in the same document that element creation was invoked in"_string)); |
604 | | |
605 | | // 9. If result’s local name is not equal to localName, then throw a "NotSupportedError" DOMException. |
606 | 0 | if (element->local_name() != local_name) |
607 | 0 | return JS::throw_completion(WebIDL::NotSupportedError::create(realm, "Synchronously created custom element must have the same local name that element creation was invoked with"_string)); |
608 | | |
609 | | // 10. Set result’s namespace prefix to prefix. |
610 | 0 | element->set_prefix(prefix); |
611 | | |
612 | | // 11. Set result’s is value to null. |
613 | 0 | element->set_is_value(Optional<String> {}); |
614 | 0 | return element; |
615 | 0 | }; |
616 | |
|
617 | 0 | auto result = synchronously_upgrade_custom_element(); |
618 | | |
619 | | // If any of these steps threw an exception, then: |
620 | 0 | if (result.is_throw_completion()) { |
621 | | // 1. Report the exception. |
622 | 0 | HTML::report_exception(result, realm); |
623 | | |
624 | | // 2. Set result to a new element that implements the HTMLUnknownElement interface, with no attributes, namespace set to the HTML namespace, namespace prefix set to prefix, |
625 | | // local name set to localName, custom element state set to "failed", custom element definition set to null, is value set to null, and node document set to document. |
626 | 0 | JS::NonnullGCPtr<Element> element = realm.heap().allocate<HTML::HTMLUnknownElement>(realm, document, QualifiedName { local_name, prefix, Namespace::HTML }); |
627 | 0 | element->set_custom_element_state(CustomElementState::Failed); |
628 | 0 | return element; |
629 | 0 | } |
630 | | |
631 | 0 | return result.release_value(); |
632 | 0 | } |
633 | | |
634 | | // 2. Otherwise: |
635 | | // 1. Set result to a new element that implements the HTMLElement interface, with no attributes, namespace set to the HTML namespace, namespace prefix set to prefix, |
636 | | // local name set to localName, custom element state set to "undefined", custom element definition set to null, is value set to null, and node document set to document. |
637 | 0 | auto element = realm.heap().allocate<HTML::HTMLElement>(realm, document, QualifiedName { local_name, prefix, Namespace::HTML }); |
638 | 0 | element->set_custom_element_state(CustomElementState::Undefined); |
639 | | |
640 | | // 2. Enqueue a custom element upgrade reaction given result and definition. |
641 | 0 | element->enqueue_a_custom_element_upgrade_reaction(*definition); |
642 | 0 | return element; |
643 | 0 | } |
644 | | |
645 | | // 7. Otherwise: |
646 | | // 1. Let interface be the element interface for localName and namespace. |
647 | | // 2. Set result to a new element that implements interface, with no attributes, namespace set to namespace, namespace prefix set to prefix, |
648 | | // local name set to localName, custom element state set to "uncustomized", custom element definition set to null, is value set to is, |
649 | | // and node document set to document. |
650 | | |
651 | 0 | auto qualified_name = QualifiedName { local_name, prefix, namespace_ }; |
652 | |
|
653 | 0 | if (namespace_ == Namespace::HTML) { |
654 | 0 | auto element = create_html_element(realm, document, move(qualified_name)); |
655 | 0 | element->set_is_value(move(is_value)); |
656 | 0 | element->set_custom_element_state(CustomElementState::Uncustomized); |
657 | | |
658 | | // 3. If namespace is the HTML namespace, and either localName is a valid custom element name or is is non-null, |
659 | | // then set result’s custom element state to "undefined". |
660 | 0 | if (HTML::is_valid_custom_element_name(local_name) || is_value.has_value()) |
661 | 0 | element->set_custom_element_state(CustomElementState::Undefined); |
662 | |
|
663 | 0 | return element; |
664 | 0 | } |
665 | | |
666 | 0 | if (namespace_ == Namespace::SVG) { |
667 | 0 | auto element = create_svg_element(realm, document, qualified_name); |
668 | 0 | element->set_is_value(move(is_value)); |
669 | 0 | element->set_custom_element_state(CustomElementState::Uncustomized); |
670 | 0 | return element; |
671 | 0 | } |
672 | | |
673 | 0 | if (namespace_ == Namespace::MathML) { |
674 | 0 | auto element = create_mathml_element(realm, document, qualified_name); |
675 | 0 | element->set_is_value(move(is_value)); |
676 | 0 | element->set_custom_element_state(CustomElementState::Uncustomized); |
677 | 0 | return element; |
678 | 0 | } |
679 | | |
680 | | // 8. Return result. |
681 | | // NOTE: See step 3. |
682 | | |
683 | | // https://dom.spec.whatwg.org/#concept-element-interface |
684 | | // The element interface for any name and namespace is Element, unless stated otherwise. |
685 | 0 | dbgln("Potential FIXME: Creating unknown generic element '{}' in namespace '{}'", local_name, namespace_); |
686 | 0 | auto element = realm.heap().allocate<DOM::Element>(realm, document, move(qualified_name)); |
687 | 0 | element->set_is_value(move(is_value)); |
688 | 0 | element->set_custom_element_state(CustomElementState::Uncustomized); |
689 | 0 | return element; |
690 | 0 | } |
691 | | |
692 | | } |