LibWeb: Make document.createElementNS() case-sensitive

Previously, when creating a HTML element with
`document.createElementNS()` we would convert the given local name to
lowercase before deciding which element type to return. We now no
longer perform this lower case conversion, so if an uppercase local
name is provided, an element of type `HTMLUnknownElement` will be
returned. This aligns our implementation with the specification.
This commit is contained in:
Tim Ledbetter 2024-07-24 23:55:15 +01:00 committed by Andreas Kling
parent e5deaa1c07
commit 5a796629c6
Notes: github-actions[bot] 2024-07-25 11:13:23 +00:00
3 changed files with 91 additions and 71 deletions

View File

@ -0,0 +1,4 @@
document.createElementNS(HTMLNS, "DIV") is instance of HTMLUnknownElement: true
document.createElementNS(HTMLNS, "div") is instance of HTMLDivElement: true
document.createElement("DIV") is instance of HTMLDivElement: true
document.createElement("div") is instance of HTMLDivElement: true

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
test(() => {
const HTMLNS = "http://www.w3.org/1999/xhtml";
const uppercaseElement = document.createElementNS(HTMLNS, "DIV");
println(`document.createElementNS(HTMLNS, "DIV") is instance of HTMLUnknownElement: ${uppercaseElement instanceof HTMLUnknownElement}`);
const lowercaseElement = document.createElementNS(HTMLNS, "div");
println(`document.createElementNS(HTMLNS, "div") is instance of HTMLDivElement: ${lowercaseElement instanceof HTMLDivElement}`);
const uppercaseElement2 = document.createElement("DIV");
println(`document.createElement("DIV") is instance of HTMLDivElement: ${uppercaseElement2 instanceof HTMLDivElement}`);
const lowercaseElement2 = document.createElement( "div");
println(`document.createElement("div") is instance of HTMLDivElement: ${lowercaseElement2 instanceof HTMLDivElement}`);
});
</script>

View File

@ -276,148 +276,148 @@ bool is_unknown_html_element(FlyString const& tag_name)
// https://html.spec.whatwg.org/#elements-in-the-dom:element-interface
static JS::NonnullGCPtr<Element> create_html_element(JS::Realm& realm, Document& document, QualifiedName qualified_name)
{
FlyString lowercase_tag_name = MUST(Infra::to_ascii_lowercase(qualified_name.local_name()));
FlyString tag_name = qualified_name.local_name();
if (lowercase_tag_name == HTML::TagNames::a)
if (tag_name == HTML::TagNames::a)
return realm.heap().allocate<HTML::HTMLAnchorElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::area)
if (tag_name == HTML::TagNames::area)
return realm.heap().allocate<HTML::HTMLAreaElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::audio)
if (tag_name == HTML::TagNames::audio)
return realm.heap().allocate<HTML::HTMLAudioElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::base)
if (tag_name == HTML::TagNames::base)
return realm.heap().allocate<HTML::HTMLBaseElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::body)
if (tag_name == HTML::TagNames::body)
return realm.heap().allocate<HTML::HTMLBodyElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::br)
if (tag_name == HTML::TagNames::br)
return realm.heap().allocate<HTML::HTMLBRElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::button)
if (tag_name == HTML::TagNames::button)
return realm.heap().allocate<HTML::HTMLButtonElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::canvas)
if (tag_name == HTML::TagNames::canvas)
return realm.heap().allocate<HTML::HTMLCanvasElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::data)
if (tag_name == HTML::TagNames::data)
return realm.heap().allocate<HTML::HTMLDataElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::datalist)
if (tag_name == HTML::TagNames::datalist)
return realm.heap().allocate<HTML::HTMLDataListElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::details)
if (tag_name == HTML::TagNames::details)
return realm.heap().allocate<HTML::HTMLDetailsElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::dialog)
if (tag_name == HTML::TagNames::dialog)
return realm.heap().allocate<HTML::HTMLDialogElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::dir)
if (tag_name == HTML::TagNames::dir)
return realm.heap().allocate<HTML::HTMLDirectoryElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::div)
if (tag_name == HTML::TagNames::div)
return realm.heap().allocate<HTML::HTMLDivElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::dl)
if (tag_name == HTML::TagNames::dl)
return realm.heap().allocate<HTML::HTMLDListElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::embed)
if (tag_name == HTML::TagNames::embed)
return realm.heap().allocate<HTML::HTMLEmbedElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::fieldset)
if (tag_name == HTML::TagNames::fieldset)
return realm.heap().allocate<HTML::HTMLFieldSetElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::font)
if (tag_name == HTML::TagNames::font)
return realm.heap().allocate<HTML::HTMLFontElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::form)
if (tag_name == HTML::TagNames::form)
return realm.heap().allocate<HTML::HTMLFormElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::frame)
if (tag_name == HTML::TagNames::frame)
return realm.heap().allocate<HTML::HTMLFrameElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::frameset)
if (tag_name == HTML::TagNames::frameset)
return realm.heap().allocate<HTML::HTMLFrameSetElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::head)
if (tag_name == HTML::TagNames::head)
return realm.heap().allocate<HTML::HTMLHeadElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6))
if (tag_name.is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6))
return realm.heap().allocate<HTML::HTMLHeadingElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::hr)
if (tag_name == HTML::TagNames::hr)
return realm.heap().allocate<HTML::HTMLHRElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::html)
if (tag_name == HTML::TagNames::html)
return realm.heap().allocate<HTML::HTMLHtmlElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::iframe)
if (tag_name == HTML::TagNames::iframe)
return realm.heap().allocate<HTML::HTMLIFrameElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::img)
if (tag_name == HTML::TagNames::img)
return realm.heap().allocate<HTML::HTMLImageElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::input)
if (tag_name == HTML::TagNames::input)
return realm.heap().allocate<HTML::HTMLInputElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::label)
if (tag_name == HTML::TagNames::label)
return realm.heap().allocate<HTML::HTMLLabelElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::legend)
if (tag_name == HTML::TagNames::legend)
return realm.heap().allocate<HTML::HTMLLegendElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::li)
if (tag_name == HTML::TagNames::li)
return realm.heap().allocate<HTML::HTMLLIElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::link)
if (tag_name == HTML::TagNames::link)
return realm.heap().allocate<HTML::HTMLLinkElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::map)
if (tag_name == HTML::TagNames::map)
return realm.heap().allocate<HTML::HTMLMapElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::marquee)
if (tag_name == HTML::TagNames::marquee)
return realm.heap().allocate<HTML::HTMLMarqueeElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::menu)
if (tag_name == HTML::TagNames::menu)
return realm.heap().allocate<HTML::HTMLMenuElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::meta)
if (tag_name == HTML::TagNames::meta)
return realm.heap().allocate<HTML::HTMLMetaElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::meter)
if (tag_name == HTML::TagNames::meter)
return realm.heap().allocate<HTML::HTMLMeterElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(HTML::TagNames::ins, HTML::TagNames::del))
if (tag_name.is_one_of(HTML::TagNames::ins, HTML::TagNames::del))
return realm.heap().allocate<HTML::HTMLModElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::object)
if (tag_name == HTML::TagNames::object)
return realm.heap().allocate<HTML::HTMLObjectElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::ol)
if (tag_name == HTML::TagNames::ol)
return realm.heap().allocate<HTML::HTMLOListElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::optgroup)
if (tag_name == HTML::TagNames::optgroup)
return realm.heap().allocate<HTML::HTMLOptGroupElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::option)
if (tag_name == HTML::TagNames::option)
return realm.heap().allocate<HTML::HTMLOptionElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::output)
if (tag_name == HTML::TagNames::output)
return realm.heap().allocate<HTML::HTMLOutputElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::p)
if (tag_name == HTML::TagNames::p)
return realm.heap().allocate<HTML::HTMLParagraphElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::param)
if (tag_name == HTML::TagNames::param)
return realm.heap().allocate<HTML::HTMLParamElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::picture)
if (tag_name == HTML::TagNames::picture)
return realm.heap().allocate<HTML::HTMLPictureElement>(realm, document, move(qualified_name));
// NOTE: The obsolete elements "listing" and "xmp" are explicitly mapped to HTMLPreElement in the specification.
if (lowercase_tag_name.is_one_of(HTML::TagNames::pre, HTML::TagNames::listing, HTML::TagNames::xmp))
if (tag_name.is_one_of(HTML::TagNames::pre, HTML::TagNames::listing, HTML::TagNames::xmp))
return realm.heap().allocate<HTML::HTMLPreElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::progress)
if (tag_name == HTML::TagNames::progress)
return realm.heap().allocate<HTML::HTMLProgressElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(HTML::TagNames::blockquote, HTML::TagNames::q))
if (tag_name.is_one_of(HTML::TagNames::blockquote, HTML::TagNames::q))
return realm.heap().allocate<HTML::HTMLQuoteElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::script)
if (tag_name == HTML::TagNames::script)
return realm.heap().allocate<HTML::HTMLScriptElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::select)
if (tag_name == HTML::TagNames::select)
return realm.heap().allocate<HTML::HTMLSelectElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::slot)
if (tag_name == HTML::TagNames::slot)
return realm.heap().allocate<HTML::HTMLSlotElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::source)
if (tag_name == HTML::TagNames::source)
return realm.heap().allocate<HTML::HTMLSourceElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::span)
if (tag_name == HTML::TagNames::span)
return realm.heap().allocate<HTML::HTMLSpanElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::style)
if (tag_name == HTML::TagNames::style)
return realm.heap().allocate<HTML::HTMLStyleElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::summary)
if (tag_name == HTML::TagNames::summary)
return realm.heap().allocate<HTML::HTMLSummaryElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::caption)
if (tag_name == HTML::TagNames::caption)
return realm.heap().allocate<HTML::HTMLTableCaptionElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(Web::HTML::TagNames::td, Web::HTML::TagNames::th))
if (tag_name.is_one_of(Web::HTML::TagNames::td, Web::HTML::TagNames::th))
return realm.heap().allocate<HTML::HTMLTableCellElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(HTML::TagNames::colgroup, HTML::TagNames::col))
if (tag_name.is_one_of(HTML::TagNames::colgroup, HTML::TagNames::col))
return realm.heap().allocate<HTML::HTMLTableColElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::table)
if (tag_name == HTML::TagNames::table)
return realm.heap().allocate<HTML::HTMLTableElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::tr)
if (tag_name == HTML::TagNames::tr)
return realm.heap().allocate<HTML::HTMLTableRowElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(HTML::TagNames::tbody, HTML::TagNames::thead, HTML::TagNames::tfoot))
if (tag_name.is_one_of(HTML::TagNames::tbody, HTML::TagNames::thead, HTML::TagNames::tfoot))
return realm.heap().allocate<HTML::HTMLTableSectionElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::template_)
if (tag_name == HTML::TagNames::template_)
return realm.heap().allocate<HTML::HTMLTemplateElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::textarea)
if (tag_name == HTML::TagNames::textarea)
return realm.heap().allocate<HTML::HTMLTextAreaElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::time)
if (tag_name == HTML::TagNames::time)
return realm.heap().allocate<HTML::HTMLTimeElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::title)
if (tag_name == HTML::TagNames::title)
return realm.heap().allocate<HTML::HTMLTitleElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::track)
if (tag_name == HTML::TagNames::track)
return realm.heap().allocate<HTML::HTMLTrackElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::ul)
if (tag_name == HTML::TagNames::ul)
return realm.heap().allocate<HTML::HTMLUListElement>(realm, document, move(qualified_name));
if (lowercase_tag_name == HTML::TagNames::video)
if (tag_name == HTML::TagNames::video)
return realm.heap().allocate<HTML::HTMLVideoElement>(realm, document, move(qualified_name));
if (lowercase_tag_name.is_one_of(
if (tag_name.is_one_of(
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,
// Obsolete
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))