소스 검색

LibWeb: Run the object representation task when the active state changes

Currently, the following JS snippet will hang indefinitely:

    new DOMParser().parseFromString("<object>", "text/html");

Because the document into which the object is inserted is not active. So
the task queued to run the representation steps will never run.

This patch implements the spec steps to rerun the representation steps
when the active state changes, and avoid the hang when the object is
created in an inactive document.
Timothy Flynn 7 달 전
부모
커밋
68164aa7ec

+ 20 - 0
Libraries/LibWeb/HTML/HTMLObjectElement.cpp

@@ -13,6 +13,7 @@
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/DocumentLoadEventDelayer.h>
 #include <LibWeb/DOM/DocumentLoading.h>
+#include <LibWeb/DOM/DocumentObserver.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/Fetch/Fetching/Fetching.h>
 #include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
@@ -54,12 +55,27 @@ void HTMLObjectElement::initialize(JS::Realm& realm)
 {
     Base::initialize(realm);
     WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLObjectElement);
+
+    m_document_observer = realm.create<DOM::DocumentObserver>(realm, document());
+
+    // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
+    // Whenever one of the following conditions occur:
+    // - the element's node document changes whether it is fully active,
+    // ...the user agent must queue an element task on the DOM manipulation task source given the object element to run
+    // the following steps to (re)determine what the object element represents.
+    m_document_observer->set_document_became_active([this]() {
+        queue_element_task_to_run_object_representation_steps();
+    });
+    m_document_observer->set_document_became_inactive([this]() {
+        queue_element_task_to_run_object_representation_steps();
+    });
 }
 
 void HTMLObjectElement::visit_edges(Cell::Visitor& visitor)
 {
     Base::visit_edges(visitor);
     visitor.visit(m_resource_request);
+    visitor.visit(m_document_observer);
 }
 
 void HTMLObjectElement::form_associated_element_attribute_changed(FlyString const& name, Optional<String> const&)
@@ -186,6 +202,10 @@ bool HTMLObjectElement::has_ancestor_media_element_or_object_element_not_showing
 // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element:queue-an-element-task
 void HTMLObjectElement::queue_element_task_to_run_object_representation_steps()
 {
+    // AD-HOC: If the document isn't fully active, this task will never run, and we will indefinitely delay the load event.
+    if (!document().is_fully_active())
+        return;
+
     // This task being queued or actively running must delay the load event of the element's node document.
     m_document_load_event_delayer_for_object_representation_task.emplace(document());
 

+ 2 - 0
Libraries/LibWeb/HTML/HTMLObjectElement.h

@@ -90,6 +90,8 @@ private:
 
     GC::Ptr<SharedResourceRequest> m_resource_request;
 
+    GC::Ptr<DOM::DocumentObserver> m_document_observer;
+
     Optional<DOM::DocumentLoadEventDelayer> m_document_load_event_delayer_for_object_representation_task;
     Optional<DOM::DocumentLoadEventDelayer> m_document_load_event_delayer_for_resource_load;
 };

+ 435 - 0
Tests/LibWeb/Text/expected/wpt-import/html/semantics/interfaces.txt

@@ -0,0 +1,435 @@
+Harness status: OK
+
+Found 429 tests
+
+426 Pass
+3 Fail
+Pass	Interfaces for a: useNS
+Pass	Interfaces for a: useParser
+Pass	Interfaces for A: createElement
+Pass	Interfaces for abbr: useNS
+Pass	Interfaces for abbr: useParser
+Pass	Interfaces for ABBR: createElement
+Pass	Interfaces for acronym: useNS
+Pass	Interfaces for acronym: useParser
+Pass	Interfaces for ACRONYM: createElement
+Pass	Interfaces for address: useNS
+Pass	Interfaces for address: useParser
+Pass	Interfaces for ADDRESS: createElement
+Pass	Interfaces for applet: useNS
+Pass	Interfaces for applet: useParser
+Pass	Interfaces for APPLET: createElement
+Pass	Interfaces for area: useNS
+Pass	Interfaces for area: useParser
+Pass	Interfaces for AREA: createElement
+Pass	Interfaces for article: useNS
+Pass	Interfaces for article: useParser
+Pass	Interfaces for ARTICLE: createElement
+Pass	Interfaces for aside: useNS
+Pass	Interfaces for aside: useParser
+Pass	Interfaces for ASIDE: createElement
+Pass	Interfaces for audio: useNS
+Pass	Interfaces for audio: useParser
+Pass	Interfaces for AUDIO: createElement
+Pass	Interfaces for b: useNS
+Pass	Interfaces for b: useParser
+Pass	Interfaces for B: createElement
+Pass	Interfaces for base: useNS
+Pass	Interfaces for base: useParser
+Pass	Interfaces for BASE: createElement
+Pass	Interfaces for basefont: useNS
+Pass	Interfaces for basefont: useParser
+Pass	Interfaces for BASEFONT: createElement
+Pass	Interfaces for bdi: useNS
+Pass	Interfaces for bdi: useParser
+Pass	Interfaces for BDI: createElement
+Pass	Interfaces for bdo: useNS
+Pass	Interfaces for bdo: useParser
+Pass	Interfaces for BDO: createElement
+Pass	Interfaces for bgsound: useNS
+Pass	Interfaces for bgsound: useParser
+Pass	Interfaces for BGSOUND: createElement
+Pass	Interfaces for big: useNS
+Pass	Interfaces for big: useParser
+Pass	Interfaces for BIG: createElement
+Pass	Interfaces for blink: useNS
+Pass	Interfaces for blink: useParser
+Pass	Interfaces for BLINK: createElement
+Pass	Interfaces for blockquote: useNS
+Pass	Interfaces for blockquote: useParser
+Pass	Interfaces for BLOCKQUOTE: createElement
+Pass	Interfaces for body: useNS
+Pass	Interfaces for body: useParser
+Pass	Interfaces for BODY: createElement
+Pass	Interfaces for br: useNS
+Pass	Interfaces for br: useParser
+Pass	Interfaces for BR: createElement
+Pass	Interfaces for button: useNS
+Pass	Interfaces for button: useParser
+Pass	Interfaces for BUTTON: createElement
+Pass	Interfaces for canvas: useNS
+Pass	Interfaces for canvas: useParser
+Pass	Interfaces for CANVAS: createElement
+Pass	Interfaces for caption: useNS
+Pass	Interfaces for CAPTION: createElement
+Pass	Interfaces for center: useNS
+Pass	Interfaces for center: useParser
+Pass	Interfaces for CENTER: createElement
+Pass	Interfaces for cite: useNS
+Pass	Interfaces for cite: useParser
+Pass	Interfaces for CITE: createElement
+Pass	Interfaces for code: useNS
+Pass	Interfaces for code: useParser
+Pass	Interfaces for CODE: createElement
+Pass	Interfaces for col: useNS
+Pass	Interfaces for COL: createElement
+Pass	Interfaces for colgroup: useNS
+Pass	Interfaces for COLGROUP: createElement
+Pass	Interfaces for command: useNS
+Pass	Interfaces for command: useParser
+Pass	Interfaces for COMMAND: createElement
+Pass	Interfaces for data: useNS
+Pass	Interfaces for data: useParser
+Pass	Interfaces for DATA: createElement
+Pass	Interfaces for datalist: useNS
+Pass	Interfaces for datalist: useParser
+Pass	Interfaces for DATALIST: createElement
+Pass	Interfaces for dd: useNS
+Pass	Interfaces for dd: useParser
+Pass	Interfaces for DD: createElement
+Pass	Interfaces for del: useNS
+Pass	Interfaces for del: useParser
+Pass	Interfaces for DEL: createElement
+Pass	Interfaces for details: useNS
+Pass	Interfaces for details: useParser
+Pass	Interfaces for DETAILS: createElement
+Pass	Interfaces for dfn: useNS
+Pass	Interfaces for dfn: useParser
+Pass	Interfaces for DFN: createElement
+Pass	Interfaces for dialog: useNS
+Pass	Interfaces for dialog: useParser
+Pass	Interfaces for DIALOG: createElement
+Pass	Interfaces for dir: useNS
+Pass	Interfaces for dir: useParser
+Pass	Interfaces for DIR: createElement
+Pass	Interfaces for directory: useNS
+Pass	Interfaces for directory: useParser
+Pass	Interfaces for DIRECTORY: createElement
+Pass	Interfaces for div: useNS
+Pass	Interfaces for div: useParser
+Pass	Interfaces for DIV: createElement
+Pass	Interfaces for dl: useNS
+Pass	Interfaces for dl: useParser
+Pass	Interfaces for DL: createElement
+Pass	Interfaces for dt: useNS
+Pass	Interfaces for dt: useParser
+Pass	Interfaces for DT: createElement
+Pass	Interfaces for em: useNS
+Pass	Interfaces for em: useParser
+Pass	Interfaces for EM: createElement
+Pass	Interfaces for embed: useNS
+Pass	Interfaces for embed: useParser
+Pass	Interfaces for EMBED: createElement
+Pass	Interfaces for fieldset: useNS
+Pass	Interfaces for fieldset: useParser
+Pass	Interfaces for FIELDSET: createElement
+Pass	Interfaces for figcaption: useNS
+Pass	Interfaces for figcaption: useParser
+Pass	Interfaces for FIGCAPTION: createElement
+Pass	Interfaces for figure: useNS
+Pass	Interfaces for figure: useParser
+Pass	Interfaces for FIGURE: createElement
+Pass	Interfaces for font: useNS
+Pass	Interfaces for font: useParser
+Pass	Interfaces for FONT: createElement
+Pass	Interfaces for foo-BAR: useNS
+Pass	Interfaces for foo-bar: useNS
+Pass	Interfaces for foo-bar: useParser
+Pass	Interfaces for FOO-BAR: createElement
+Pass	Interfaces for foo: useNS
+Pass	Interfaces for foo: useParser
+Pass	Interfaces for FOO: createElement
+Pass	Interfaces for footer: useNS
+Pass	Interfaces for footer: useParser
+Pass	Interfaces for FOOTER: createElement
+Pass	Interfaces for form: useNS
+Pass	Interfaces for form: useParser
+Pass	Interfaces for FORM: createElement
+Pass	Interfaces for frame: useNS
+Pass	Interfaces for FRAME: createElement
+Pass	Interfaces for frameset: useNS
+Pass	Interfaces for FRAMESET: createElement
+Pass	Interfaces for h1: useNS
+Pass	Interfaces for h1: useParser
+Pass	Interfaces for H1: createElement
+Pass	Interfaces for h2: useNS
+Pass	Interfaces for h2: useParser
+Pass	Interfaces for H2: createElement
+Pass	Interfaces for h3: useNS
+Pass	Interfaces for h3: useParser
+Pass	Interfaces for H3: createElement
+Pass	Interfaces for h4: useNS
+Pass	Interfaces for h4: useParser
+Pass	Interfaces for H4: createElement
+Pass	Interfaces for h5: useNS
+Pass	Interfaces for h5: useParser
+Pass	Interfaces for H5: createElement
+Pass	Interfaces for h6: useNS
+Pass	Interfaces for h6: useParser
+Pass	Interfaces for H6: createElement
+Pass	Interfaces for head: useNS
+Pass	Interfaces for head: useParser
+Pass	Interfaces for HEAD: createElement
+Pass	Interfaces for header: useNS
+Pass	Interfaces for header: useParser
+Pass	Interfaces for HEADER: createElement
+Pass	Interfaces for hgroup: useNS
+Pass	Interfaces for hgroup: useParser
+Pass	Interfaces for HGROUP: createElement
+Pass	Interfaces for hr: useNS
+Pass	Interfaces for hr: useParser
+Pass	Interfaces for HR: createElement
+Pass	Interfaces for html: useNS
+Pass	Interfaces for html: useParser
+Pass	Interfaces for HTML: createElement
+Pass	Interfaces for i: useNS
+Pass	Interfaces for i: useParser
+Pass	Interfaces for I: createElement
+Pass	Interfaces for iframe: useNS
+Pass	Interfaces for iframe: useParser
+Pass	Interfaces for IFRAME: createElement
+Pass	Interfaces for image: useNS
+Pass	Interfaces for IMAGE: createElement
+Pass	Interfaces for img: useNS
+Pass	Interfaces for img: useParser
+Pass	Interfaces for IMG: createElement
+Pass	Interfaces for input: useNS
+Pass	Interfaces for input: useParser
+Pass	Interfaces for INPUT: createElement
+Pass	Interfaces for ins: useNS
+Pass	Interfaces for ins: useParser
+Pass	Interfaces for INS: createElement
+Pass	Interfaces for isindex: useNS
+Pass	Interfaces for isindex: useParser
+Pass	Interfaces for ISINDEX: createElement
+Pass	Interfaces for kbd: useNS
+Pass	Interfaces for kbd: useParser
+Pass	Interfaces for KBD: createElement
+Pass	Interfaces for keygen: useNS
+Pass	Interfaces for keygen: useParser
+Pass	Interfaces for KEYGEN: createElement
+Pass	Interfaces for label: useNS
+Pass	Interfaces for label: useParser
+Pass	Interfaces for LABEL: createElement
+Pass	Interfaces for legend: useNS
+Pass	Interfaces for legend: useParser
+Pass	Interfaces for LEGEND: createElement
+Pass	Interfaces for li: useNS
+Pass	Interfaces for li: useParser
+Pass	Interfaces for LI: createElement
+Pass	Interfaces for link: useNS
+Pass	Interfaces for link: useParser
+Pass	Interfaces for LINK: createElement
+Pass	Interfaces for listing: useNS
+Pass	Interfaces for listing: useParser
+Pass	Interfaces for LISTING: createElement
+Pass	Interfaces for main: useNS
+Pass	Interfaces for main: useParser
+Pass	Interfaces for MAIN: createElement
+Pass	Interfaces for map: useNS
+Pass	Interfaces for map: useParser
+Pass	Interfaces for MAP: createElement
+Pass	Interfaces for mark: useNS
+Pass	Interfaces for mark: useParser
+Pass	Interfaces for MARK: createElement
+Pass	Interfaces for marquee: useNS
+Pass	Interfaces for marquee: useParser
+Pass	Interfaces for MARQUEE: createElement
+Pass	Interfaces for menu: useNS
+Pass	Interfaces for menu: useParser
+Pass	Interfaces for MENU: createElement
+Pass	Interfaces for meta: useNS
+Pass	Interfaces for meta: useParser
+Pass	Interfaces for META: createElement
+Pass	Interfaces for meter: useNS
+Pass	Interfaces for meter: useParser
+Pass	Interfaces for METER: createElement
+Pass	Interfaces for mod: useNS
+Pass	Interfaces for mod: useParser
+Pass	Interfaces for MOD: createElement
+Pass	Interfaces for multicol: useNS
+Pass	Interfaces for multicol: useParser
+Pass	Interfaces for MULTICOL: createElement
+Pass	Interfaces for nav: useNS
+Pass	Interfaces for nav: useParser
+Pass	Interfaces for NAV: createElement
+Pass	Interfaces for nextid: useNS
+Pass	Interfaces for nextid: useParser
+Pass	Interfaces for NEXTID: createElement
+Pass	Interfaces for nobr: useNS
+Pass	Interfaces for nobr: useParser
+Pass	Interfaces for NOBR: createElement
+Pass	Interfaces for noembed: useNS
+Pass	Interfaces for noembed: useParser
+Pass	Interfaces for NOEMBED: createElement
+Pass	Interfaces for noframes: useNS
+Pass	Interfaces for noframes: useParser
+Pass	Interfaces for NOFRAMES: createElement
+Pass	Interfaces for noscript: useNS
+Pass	Interfaces for noscript: useParser
+Pass	Interfaces for NOSCRIPT: createElement
+Pass	Interfaces for object: useNS
+Pass	Interfaces for object: useParser
+Pass	Interfaces for OBJECT: createElement
+Pass	Interfaces for ol: useNS
+Pass	Interfaces for ol: useParser
+Pass	Interfaces for OL: createElement
+Pass	Interfaces for optgroup: useNS
+Pass	Interfaces for optgroup: useParser
+Pass	Interfaces for OPTGROUP: createElement
+Pass	Interfaces for option: useNS
+Pass	Interfaces for option: useParser
+Pass	Interfaces for OPTION: createElement
+Pass	Interfaces for output: useNS
+Pass	Interfaces for output: useParser
+Pass	Interfaces for OUTPUT: createElement
+Pass	Interfaces for p: useNS
+Pass	Interfaces for p: useParser
+Pass	Interfaces for P: createElement
+Pass	Interfaces for param: useNS
+Pass	Interfaces for param: useParser
+Pass	Interfaces for PARAM: createElement
+Fail	Interfaces for permission: useNS
+Fail	Interfaces for permission: useParser
+Fail	Interfaces for PERMISSION: createElement
+Pass	Interfaces for picture: useNS
+Pass	Interfaces for picture: useParser
+Pass	Interfaces for PICTURE: createElement
+Pass	Interfaces for plaintext: useNS
+Pass	Interfaces for plaintext: useParser
+Pass	Interfaces for PLAINTEXT: createElement
+Pass	Interfaces for pre: useNS
+Pass	Interfaces for pre: useParser
+Pass	Interfaces for PRE: createElement
+Pass	Interfaces for progress: useNS
+Pass	Interfaces for progress: useParser
+Pass	Interfaces for PROGRESS: createElement
+Pass	Interfaces for q: useNS
+Pass	Interfaces for q: useParser
+Pass	Interfaces for Q: createElement
+Pass	Interfaces for quasit: useNS
+Pass	Interfaces for quasit: useParser
+Pass	Interfaces for QUASIT: createElement
+Pass	Interfaces for rb: useNS
+Pass	Interfaces for rb: useParser
+Pass	Interfaces for RB: createElement
+Pass	Interfaces for rp: useNS
+Pass	Interfaces for rp: useParser
+Pass	Interfaces for RP: createElement
+Pass	Interfaces for rt: useNS
+Pass	Interfaces for rt: useParser
+Pass	Interfaces for RT: createElement
+Pass	Interfaces for rtc: useNS
+Pass	Interfaces for rtc: useParser
+Pass	Interfaces for RTC: createElement
+Pass	Interfaces for ruby: useNS
+Pass	Interfaces for ruby: useParser
+Pass	Interfaces for RUBY: createElement
+Pass	Interfaces for s: useNS
+Pass	Interfaces for s: useParser
+Pass	Interfaces for S: createElement
+Pass	Interfaces for samp: useNS
+Pass	Interfaces for samp: useParser
+Pass	Interfaces for SAMP: createElement
+Pass	Interfaces for script: useNS
+Pass	Interfaces for script: useParser
+Pass	Interfaces for SCRIPT: createElement
+Pass	Interfaces for section: useNS
+Pass	Interfaces for section: useParser
+Pass	Interfaces for SECTION: createElement
+Pass	Interfaces for select: useNS
+Pass	Interfaces for select: useParser
+Pass	Interfaces for SELECT: createElement
+Pass	Interfaces for slot: useNS
+Pass	Interfaces for slot: useParser
+Pass	Interfaces for SLOT: createElement
+Pass	Interfaces for small: useNS
+Pass	Interfaces for small: useParser
+Pass	Interfaces for SMALL: createElement
+Pass	Interfaces for source: useNS
+Pass	Interfaces for source: useParser
+Pass	Interfaces for SOURCE: createElement
+Pass	Interfaces for spacer: useNS
+Pass	Interfaces for spacer: useParser
+Pass	Interfaces for SPACER: createElement
+Pass	Interfaces for span: useNS
+Pass	Interfaces for span: useParser
+Pass	Interfaces for SPAN: createElement
+Pass	Interfaces for strike: useNS
+Pass	Interfaces for strike: useParser
+Pass	Interfaces for STRIKE: createElement
+Pass	Interfaces for strong: useNS
+Pass	Interfaces for strong: useParser
+Pass	Interfaces for STRONG: createElement
+Pass	Interfaces for style: useNS
+Pass	Interfaces for style: useParser
+Pass	Interfaces for STYLE: createElement
+Pass	Interfaces for sub: useNS
+Pass	Interfaces for sub: useParser
+Pass	Interfaces for SUB: createElement
+Pass	Interfaces for summary: useNS
+Pass	Interfaces for summary: useParser
+Pass	Interfaces for SUMMARY: createElement
+Pass	Interfaces for sup: useNS
+Pass	Interfaces for sup: useParser
+Pass	Interfaces for SUP: createElement
+Pass	Interfaces for table: useNS
+Pass	Interfaces for table: useParser
+Pass	Interfaces for TABLE: createElement
+Pass	Interfaces for tbody: useNS
+Pass	Interfaces for TBODY: createElement
+Pass	Interfaces for td: useNS
+Pass	Interfaces for TD: createElement
+Pass	Interfaces for textarea: useNS
+Pass	Interfaces for textarea: useParser
+Pass	Interfaces for TEXTAREA: createElement
+Pass	Interfaces for tfoot: useNS
+Pass	Interfaces for TFOOT: createElement
+Pass	Interfaces for th: useNS
+Pass	Interfaces for TH: createElement
+Pass	Interfaces for thead: useNS
+Pass	Interfaces for THEAD: createElement
+Pass	Interfaces for time: useNS
+Pass	Interfaces for time: useParser
+Pass	Interfaces for TIME: createElement
+Pass	Interfaces for title: useNS
+Pass	Interfaces for title: useParser
+Pass	Interfaces for TITLE: createElement
+Pass	Interfaces for tr: useNS
+Pass	Interfaces for TR: createElement
+Pass	Interfaces for track: useNS
+Pass	Interfaces for track: useParser
+Pass	Interfaces for TRACK: createElement
+Pass	Interfaces for tt: useNS
+Pass	Interfaces for tt: useParser
+Pass	Interfaces for TT: createElement
+Pass	Interfaces for u: useNS
+Pass	Interfaces for u: useParser
+Pass	Interfaces for U: createElement
+Pass	Interfaces for ul: useNS
+Pass	Interfaces for ul: useParser
+Pass	Interfaces for UL: createElement
+Pass	Interfaces for var: useNS
+Pass	Interfaces for var: useParser
+Pass	Interfaces for VAR: createElement
+Pass	Interfaces for video: useNS
+Pass	Interfaces for video: useParser
+Pass	Interfaces for VIDEO: createElement
+Pass	Interfaces for wbr: useNS
+Pass	Interfaces for wbr: useParser
+Pass	Interfaces for WBR: createElement
+Pass	Interfaces for xmp: useNS
+Pass	Interfaces for xmp: useParser
+Pass	Interfaces for XMP: createElement
+Pass	Interfaces for å-bar: useNS
+Pass	Interfaces for Å-BAR: createElement

+ 74 - 0
Tests/LibWeb/Text/input/wpt-import/html/semantics/interfaces.html

@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test of interfaces</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/">
+<link rel="help" href="https://webidl.spec.whatwg.org/#host-objects">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=96">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src=interfaces.js></script>
+<div id="log"></div>
+<script>
+function do_test(local_name, iface, variant) {
+  test(function() {
+    var e;
+    var i = "HTML" + iface + "Element";
+    if (variant === "useNS") {
+      // Use createElementNS here to preserve the case of local_name.
+      e = document.createElementNS("http://www.w3.org/1999/xhtml", local_name);
+    } else if (variant === "useParser") {
+      e = new DOMParser().parseFromString("<" + local_name + ">", "text/html").querySelector(local_name);
+    } else {
+      e = document.createElement(local_name);
+    }
+    assert_class_string(e, i,
+                        "Element " + local_name + " should have " + i +
+                        " as its primary interface.");
+    assert_true(e instanceof window[i],
+                "Element " + local_name + " should implement " + i + ".");
+    assert_true(e instanceof HTMLElement,
+                "Element " + local_name + " should implement HTMLElement.");
+    assert_true(e instanceof Element,
+                "Element " + local_name + " should implement Element.");
+    assert_true(e instanceof Node,
+                "Element " + local_name + " should implement Node.");
+  }, "Interfaces for " + local_name + ": " + variant);
+}
+
+// Some elements have weird parser behavior / insertion modes and would be
+// skipped by the parser, so skip those.
+function should_do_parser_test(local_name) {
+  return ![
+    "foo-BAR",
+    "tbody",
+    "td",
+    "tfoot",
+    "th",
+    "thead",
+    "tr",
+    "å-bar",
+    "caption",
+    "col",
+    "colgroup",
+    "frame",
+    "image",
+    "frameset",
+  ].includes(local_name)
+}
+
+elements.forEach(function(a) {
+  do_test(a[0], a[1], "useNS");
+
+  if (should_do_parser_test(a[0])) {
+    do_test(a[0], a[1], "useParser");
+  }
+
+  // Only run the createElement variant if the input is all-lowercase, because createElement
+  // case-folds to lowercase. Custom elements are required to use all-lowercase to implement
+  // HTMLElement, otherwise they use HTMLUnknownElement per spec. Example: "foo-BAR".
+  if (a[0] === a[0].toLowerCase()) {
+    do_test(a[0].toUpperCase(), a[1], "createElement");
+  }
+})
+</script>

+ 150 - 0
Tests/LibWeb/Text/input/wpt-import/html/semantics/interfaces.js

@@ -0,0 +1,150 @@
+var elements = [
+  ["a", "Anchor"],
+  ["abbr", ""],
+  ["acronym", ""],
+  ["address", ""],
+  ["applet", "Unknown"],
+  ["area", "Area"],
+  ["article", ""],
+  ["aside", ""],
+  ["audio", "Audio"],
+  ["b", ""],
+  ["base", "Base"],
+  ["basefont", ""],
+  ["bdi", ""],
+  ["bdo", ""],
+  ["bgsound", "Unknown"],
+  ["big", ""],
+  ["blink", "Unknown"],
+  ["blockquote", "Quote"],
+  ["body", "Body"],
+  ["br", "BR"],
+  ["button", "Button"],
+  ["canvas", "Canvas"],
+  ["caption", "TableCaption"],
+  ["center", ""],
+  ["cite", ""],
+  ["code", ""],
+  ["col", "TableCol"],
+  ["colgroup", "TableCol"],
+  ["command", "Unknown"],
+  ["data", "Data"],
+  ["datalist", "DataList"],
+  ["dd", ""],
+  ["del", "Mod"],
+  ["details", "Details"],
+  ["dfn", ""],
+  ["dialog", "Dialog"],
+  ["dir", "Directory"],
+  ["directory", "Unknown"],
+  ["div", "Div"],
+  ["dl", "DList"],
+  ["dt", ""],
+  ["em", ""],
+  ["embed", "Embed"],
+  ["fieldset", "FieldSet"],
+  ["figcaption", ""],
+  ["figure", ""],
+  ["font", "Font"],
+  ["foo-BAR", "Unknown"], // not a valid custom element name
+  ["foo-bar", ""], // valid custom element name
+  ["foo", "Unknown"],
+  ["footer", ""],
+  ["form", "Form"],
+  ["frame", "Frame"],
+  ["frameset", "FrameSet"],
+  ["h1", "Heading"],
+  ["h2", "Heading"],
+  ["h3", "Heading"],
+  ["h4", "Heading"],
+  ["h5", "Heading"],
+  ["h6", "Heading"],
+  ["head", "Head"],
+  ["header", ""],
+  ["hgroup", ""],
+  ["hr", "HR"],
+  ["html", "Html"],
+  ["i", ""],
+  ["iframe", "IFrame"],
+  ["image", "Unknown"],
+  ["img", "Image"],
+  ["input", "Input"],
+  ["ins", "Mod"],
+  ["isindex", "Unknown"],
+  ["kbd", ""],
+  ["keygen", "Unknown"],
+  ["label", "Label"],
+  ["legend", "Legend"],
+  ["li", "LI"],
+  ["link", "Link"],
+  ["listing", "Pre"],
+  ["main", ""],
+  ["map", "Map"],
+  ["mark", ""],
+  ["marquee", "Marquee"],
+  ["menu", "Menu"],
+  ["meta", "Meta"],
+  ["meter", "Meter"],
+  ["mod", "Unknown"],
+  ["multicol", "Unknown"],
+  ["nav", ""],
+  ["nextid", "Unknown"],
+  ["nobr", ""],
+  ["noembed", ""],
+  ["noframes", ""],
+  ["noscript", ""],
+  ["object", "Object"],
+  ["ol", "OList"],
+  ["optgroup", "OptGroup"],
+  ["option", "Option"],
+  ["output", "Output"],
+  ["p", "Paragraph"],
+  ["param", "Param"],
+  ["permission", "Permission"],
+  ["picture", "Picture"],
+  ["plaintext", ""],
+  ["pre", "Pre"],
+  ["progress", "Progress"],
+  ["q", "Quote"],
+  ["quasit", "Unknown"],
+  ["rb", ""],
+  ["rp", ""],
+  ["rt", ""],
+  ["rtc", ""],
+  ["ruby", ""],
+  ["s", ""],
+  ["samp", ""],
+  ["script", "Script"],
+  ["section", ""],
+  ["select", "Select"],
+  ["slot", "Slot"],
+  ["small", ""],
+  ["source", "Source"],
+  ["spacer", "Unknown"],
+  ["span", "Span"],
+  ["strike", ""],
+  ["strong", ""],
+  ["style", "Style"],
+  ["sub", ""],
+  ["summary", ""],
+  ["sup", ""],
+  ["table", "Table"],
+  ["tbody", "TableSection"],
+  ["td", "TableCell"],
+  ["textarea", "TextArea"],
+  ["tfoot", "TableSection"],
+  ["th", "TableCell"],
+  ["thead", "TableSection"],
+  ["time", "Time"],
+  ["title", "Title"],
+  ["tr", "TableRow"],
+  ["track", "Track"],
+  ["tt", ""],
+  ["u", ""],
+  ["ul", "UList"],
+  ["var", ""],
+  ["video", "Video"],
+  ["wbr", ""],
+  ["xmp", "Pre"],
+  ["\u00E5-bar", "Unknown"], // not a valid custom element name
+];