LibWeb/HTML: Consider <a> all-named elements instead of <link>
Some checks are pending
CI / path-changes (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Blocked by required conditions
CI / Lagom (false, NO_FUZZ, macos-15, macOS, Clang) (push) Blocked by required conditions
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Blocked by required conditions
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Blocked by required conditions
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

Leaving only the unimplemented legacy [[Call]] override funkiness
of HTMLAllCollection left not passing in the WPT tests.
This commit is contained in:
Shannon Booth 2024-12-24 02:44:05 +13:00 committed by Jelle Raaijmakers
parent c70431672e
commit 910ff8b694
Notes: github-actions[bot] 2024-12-23 20:20:03 +00:00
3 changed files with 383 additions and 2 deletions

View file

@ -12,6 +12,7 @@
#include <LibWeb/DOM/ParentNode.h>
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/HTMLAllCollection.h>
#include <LibWeb/HTML/HTMLAnchorElement.h>
#include <LibWeb/HTML/HTMLButtonElement.h>
#include <LibWeb/HTML/HTMLEmbedElement.h>
#include <LibWeb/HTML/HTMLFormElement.h>
@ -20,7 +21,6 @@
#include <LibWeb/HTML/HTMLIFrameElement.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/HTML/HTMLInputElement.h>
#include <LibWeb/HTML/HTMLLinkElement.h>
#include <LibWeb/HTML/HTMLMapElement.h>
#include <LibWeb/HTML/HTMLMetaElement.h>
#include <LibWeb/HTML/HTMLObjectElement.h>
@ -68,7 +68,7 @@ void HTMLAllCollection::visit_edges(Cell::Visitor& visitor)
static bool is_all_named_element(DOM::Element const& element)
{
// The following elements are "all"-named elements: a, button, embed, form, frame, frameset, iframe, img, input, map, meta, object, select, and textarea
return is<HTML::HTMLLinkElement>(element)
return is<HTML::HTMLAnchorElement>(element)
|| is<HTML::HTMLButtonElement>(element)
|| is<HTML::HTMLEmbedElement>(element)
|| is<HTML::HTMLFormElement>(element)

View file

@ -0,0 +1,47 @@
Harness status: OK
Found 41 tests
30 Pass
11 Fail
Pass document.all is an HTMLAllCollection
Pass length attribute
Pass indexed property getter
Pass indexed property getter out of range
Pass named property getter
Pass named property getter with dot syntax
Pass named property getter with invalid name
Pass named property getter returning collection
Pass named property getter with "array index property name"
Pass named property getter with invalid "array index property name"
Pass named property getter with undefined
Pass named property getter with null
Pass namedItem method
Pass namedItem method with invalid name
Pass namedItem method returning collection
Pass namedItem method with "array index property name"
Pass namedItem method with invalid "array index property name"
Pass namedItem method with undefined
Pass namedItem method with null
Pass namedItem method with no argument
Fail legacy caller
Fail legacy caller with invalid name
Fail legacy caller returning collection
Fail legacy caller with "array index property name"
Fail legacy caller with "array index property name" as number
Fail legacy caller with invalid "array index property name"
Fail legacy caller with undefined
Fail legacy caller with null
Fail legacy caller with no argument
Pass legacy caller is not a constructor
Fail legacy caller with arbitrary this value
Pass item method
Pass item method with invalid name
Pass item method returning collection
Pass item method with "array index property name"
Pass item method with "array index property name" as number
Pass item method with invalid "array index property name"
Pass item method with undefined
Pass item method with null
Pass item method with no argument
Fail collections are new live HTMLCollection instances

View file

@ -0,0 +1,334 @@
<!DOCTYPE HTML>
<html id="root">
<head>
<title>HTMLAllCollection Tests</title>
<link rel="author" title="Dan Druta" href="mailto:dan.druta@att.com"/>
<link rel="author" title="Philip Jägenstedt" href="mailto:philip@foolip.org"/>
<link rel="help" href="https://html.spec.whatwg.org/multipage/infrastructure.html#the-htmlallcollection-interface"/>
<meta name="flags" content="TOKENS" />
<meta name="assert" content="TEST ASSERTION"/>
<script src="../../../../resources/testharness.js"></script>
<script src="../../../../resources/testharnessreport.js"></script>
</head>
<body id="tags">
<img src="../../../../images/green.png" name="picture">
<a name="foo"></a>
<a name="foo"></a>
<span id="42"></span>
<span id="043"></span>
<div id="4294967294"></div>
<div id="4294967295"></div>
<div id="4294967296"></div>
<div id="undefined"></div>
<div id="null"></div>
<div name="divwithname"></div>
<div id="-0"></div>
<div id="log"></div>
<script>
var anchors = document.querySelectorAll("a");
var divs = document.querySelectorAll("div");
var scripts = document.querySelectorAll("script");
var spans = document.querySelectorAll("span");
test(function() {
assert_true(document.all instanceof HTMLAllCollection);
}, "document.all is an HTMLAllCollection");
test(function() {
assert_equals(document.all.length, 25);
}, "length attribute");
// indexed property getter
test(function() {
assert_equals(document.all[0], document.documentElement);
assert_equals(document.all[-0], document.documentElement);
assert_equals(document.all[24], scripts[2]);
}, "indexed property getter");
test(function() {
assert_equals(document.all[-1], undefined);
assert_equals(document.all[25], undefined);
assert_equals(document.all[42], undefined);
assert_equals(document.all[43], undefined);
assert_equals(document.all[4294967294], undefined);
assert_equals(document.all[4294967295], divs[1]);
assert_equals(document.all[4294967296], divs[2]);
}, "indexed property getter out of range");
// named property getter
test(function() {
assert_equals(document.all["root"], document.documentElement);
assert_equals(document.all["flags"].content, "TOKENS");
assert_equals(document.all["picture"].tagName, "IMG");
}, "named property getter");
test(function() {
assert_equals(document.all.root, document.documentElement);
assert_equals(document.all.flags.content, "TOKENS");
assert_equals(document.all.picture.tagName, "IMG");
}, "named property getter with dot syntax");
test(function() {
assert_equals(document.all[""], undefined);
assert_equals(document.all["noname"], undefined);
assert_equals(document.all.noname, undefined);
assert_equals(document.all["divwithname"], undefined);
assert_equals(document.all.divwithname, undefined);
}, "named property getter with invalid name");
test(function() {
var collection = document.all["foo"];
assert_equals(collection.length, 2);
assert_equals(collection[0], anchors[0]);
assert_equals(collection[1], anchors[1]);
}, "named property getter returning collection");
test(function() {
assert_equals(document.all["0"], document.documentElement);
assert_equals(document.all["24"], document.scripts[2]);
assert_equals(document.all["25"], undefined);
assert_equals(document.all["42"], undefined);
assert_equals(document.all["43"], undefined);
}, "named property getter with \"array index property name\"");
test(function() {
assert_equals(document.all["00"], undefined);
assert_equals(document.all["042"], undefined);
assert_equals(document.all["043"], spans[1]);
assert_equals(document.all["4294967294"], undefined);
assert_equals(document.all["4294967295"], divs[1]);
assert_equals(document.all["4294967296"], divs[2]);
assert_equals(document.all["-0"], divs[6]);
}, "named property getter with invalid \"array index property name\"");
test(function() {
assert_equals(document.all[undefined], divs[3]);
}, "named property getter with undefined");
test(function() {
assert_equals(document.all[null], divs[4]);
}, "named property getter with null");
// namedItem method
test(function() {
assert_equals(document.all.namedItem("root"), document.documentElement);
assert_equals(document.all.namedItem("flags").content, "TOKENS");
assert_equals(document.all.namedItem("picture").tagName, "IMG");
}, "namedItem method");
test(function() {
assert_equals(document.all.namedItem(""), null);
assert_equals(document.all.namedItem("noname"), null);
assert_equals(document.all.namedItem("divwithname"), null);
}, "namedItem method with invalid name");
test(function() {
var collection = document.all.namedItem("foo");
assert_equals(collection.length, 2);
assert_equals(collection[0], anchors[0]);
assert_equals(collection[1], anchors[1]);
}, "namedItem method returning collection");
test(function() {
assert_equals(document.all.namedItem("0"), null);
assert_equals(document.all.namedItem("23"), null);
assert_equals(document.all.namedItem("24"), null);
assert_equals(document.all.namedItem("42"), spans[0]);
assert_equals(document.all.namedItem("43"), null);
}, "namedItem method with \"array index property name\"");
test(function() {
assert_equals(document.all.namedItem("00"), null);
assert_equals(document.all.namedItem("042"), null);
assert_equals(document.all.namedItem("043"), spans[1]);
assert_equals(document.all.namedItem("4294967294"), divs[0]);
assert_equals(document.all.namedItem("4294967295"), divs[1]);
assert_equals(document.all.namedItem("4294967296"), divs[2]);
assert_equals(document.all.namedItem("-0"), divs[6]);
}, "namedItem method with invalid \"array index property name\"");
test(function() {
assert_equals(document.all.namedItem(undefined), divs[3]);
}, "namedItem method with undefined");
test(function() {
assert_equals(document.all.namedItem(null), divs[4]);
}, "namedItem method with null");
test(function() {
assert_equals(document.all.namedItem.length, 1);
assert_throws_js(TypeError, function() {
document.all.namedItem();
});
}, "namedItem method with no argument");
// legacy caller
test(function() {
assert_equals(document.all("root"), document.documentElement);
assert_equals(document.all("flags").content, "TOKENS");
assert_equals(document.all("picture").tagName, "IMG");
}, "legacy caller");
test(function() {
assert_equals(document.all(""), null);
assert_equals(document.all("noname"), null);
assert_equals(document.all("divwithname"), null);
}, "legacy caller with invalid name");
test(function() {
var collection = document.all("foo");
assert_equals(collection.length, 2);
assert_equals(collection[0], anchors[0]);
assert_equals(collection[1], anchors[1]);
}, "legacy caller returning collection");
test(function() {
assert_equals(document.all("0"), document.documentElement);
assert_equals(document.all("24"), document.scripts[2]);
assert_equals(document.all("25"), null);
assert_equals(document.all("42"), null);
assert_equals(document.all("43"), null);
}, "legacy caller with \"array index property name\"");
test(function() {
assert_equals(document.all(0), document.documentElement);
assert_equals(document.all(24), document.scripts[2]);
assert_equals(document.all(25), null);
assert_equals(document.all(42), null);
assert_equals(document.all(43), null);
}, "legacy caller with \"array index property name\" as number");
test(function() {
assert_equals(document.all("00"), null);
assert_equals(document.all("042"), null);
assert_equals(document.all("043"), spans[1]);
assert_equals(document.all("4294967294"), null);
assert_equals(document.all("4294967295"), divs[1]);
assert_equals(document.all("4294967296"), divs[2]);
assert_equals(document.all("-0"), divs[6]);
}, "legacy caller with invalid \"array index property name\"");
test(function() {
assert_equals(document.all(undefined), null);
}, "legacy caller with undefined");
test(function() {
assert_equals(document.all(null), divs[4]);
}, "legacy caller with null");
test(function() {
assert_equals(document.all(), null);
}, "legacy caller with no argument");
test(function() {
assert_throws_js(TypeError, function() {
new document.all("picture");
}, "New should not work on document.all()");
// https://esdiscuss.org/topic/isconstructor#content-11
assert_throws_js(TypeError, function() {
new (new Proxy(document.all, {
construct: function() {
return {};
}
}));
}, "Proxies should treat document.all() as not-a-constructor");
}, "legacy caller is not a constructor");
test(function() {
[undefined, null, {}, document.body].forEach(function(thisValue) {
assert_equals(Function.prototype.call.call(document.all, thisValue, "043"), spans[1]);
});
}, "legacy caller with arbitrary this value");
// item method
test(function() {
assert_equals(document.all.item("root"), document.documentElement);
assert_equals(document.all.item("flags").content, "TOKENS");
assert_equals(document.all.item("picture").tagName, "IMG");
}, "item method");
test(function() {
assert_equals(document.all.item(""), null);
assert_equals(document.all.item("noname"), null);
assert_equals(document.all.item("divwithname"), null);
}, "item method with invalid name");
test(function() {
var collection = document.all.item("foo");
assert_equals(collection.length, 2);
assert_equals(collection[0], anchors[0]);
assert_equals(collection[1], anchors[1]);
}, "item method returning collection");
test(function() {
assert_equals(document.all.item("0"), document.documentElement);
assert_equals(document.all.item("24"), document.scripts[2]);
assert_equals(document.all.item("25"), null);
assert_equals(document.all.item("42"), null);
assert_equals(document.all.item("43"), null);
}, "item method with \"array index property name\"");
test(function() {
assert_equals(document.all.item(0), document.documentElement);
assert_equals(document.all.item(24), document.scripts[2]);
assert_equals(document.all.item(25), null);
assert_equals(document.all.item(42), null);
assert_equals(document.all.item(43), null);
}, "item method with \"array index property name\" as number");
test(function() {
assert_equals(document.all.item("00"), null);
assert_equals(document.all.item("042"), null);
assert_equals(document.all.item("043"), spans[1]);
assert_equals(document.all.item("4294967294"), null);
assert_equals(document.all.item("4294967295"), divs[1]);
assert_equals(document.all.item("4294967296"), divs[2]);
assert_equals(document.all.item("-0"), divs[6]);
}, "item method with invalid \"array index property name\"");
test(function() {
assert_equals(document.all.item(undefined), null);
}, "item method with undefined");
test(function() {
assert_equals(document.all.item(null), divs[4]);
}, "item method with null");
test(function() {
assert_equals(document.all.item.length, 0);
assert_equals(document.all.item(), null);
}, "item method with no argument");
// live HTMLCollection
test(function() {
var collections = [
document.all["foo"],
document.all.namedItem("foo"),
document.all("foo"),
document.all.item("foo"),
];
// a new HTMLCollection is created for each call
for (var i = 0; i < collections.length; i++) {
assert_true(collections[i] instanceof HTMLCollection);
for (var j = i + 1; j < collections.length; j++) {
assert_not_equals(collections[i], collections[j]);
}
}
for (var c of collections) {
assert_equals(c.length, 2);
}
anchors[0].name = "bar";
for (var c of collections) {
assert_equals(c.length, 1);
}
}, "collections are new live HTMLCollection instances");
</script>
</body>
</html>