Skip to content

Commit

Permalink
LibWeb: Make document.createElementNS() case-sensitive
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tcl3 committed Jul 24, 2024
1 parent 40f9c9f commit 3f12303
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 71 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
element named "DIV" is instance of HTMLUnknownElement: true
element named "div" is instance of HTMLDivElement: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
test(() => {
const HTMLNS = "http://www.w3.org/1999/xhtml";
const uppercaseElement = document.createElementNS(HTMLNS, "DIV");
println(`element named "DIV" is instance of HTMLUnknownElement: ${uppercaseElement instanceof HTMLUnknownElement}`);
const lowercaseElement = document.createElementNS(HTMLNS, "div");
println(`element named "div" is instance of HTMLDivElement: ${lowercaseElement instanceof HTMLDivElement}`);
});
</script>
142 changes: 71 additions & 71 deletions Userland/Libraries/LibWeb/DOM/ElementFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 3f12303

Please sign in to comment.