1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:38:11 +00:00

LibWeb: Support RadioNodeList named items in HTMLFormControlsCollection

We would previously not return a RadioNodeList in the curious case where
a named item resolves to two different elements within the form.

This was not a problem when calling namedItem directly in the IDL as
named_item_or_radio_node_list shadows named_item but is exposed when
calling the property through array bracket notation (as an example).

Fix this, and add a bunch more tests to cover
HTMLFormControlsCollection.
This commit is contained in:
Shannon Booth 2023-12-21 22:04:26 +13:00 committed by Andreas Kling
parent 1defc4595b
commit ec2b4c271f
4 changed files with 133 additions and 12 deletions

View file

@ -1,8 +1,87 @@
HTMLFormControlsCollection HTMLFormControlsCollection
2
-------------------
form.namedItem("formcontrol")
-------------------
RadioNodeList RadioNodeList
2 2
button button
text text
null -------------------
form.namedItem("one")
-------------------
HTMLInputElement HTMLInputElement
formcontrol
button
-------------------
form.namedItem("two")
-------------------
HTMLInputElement
formcontrol
text text
-------------------
form.namedItem("nomatch")
-------------------
null
-------------------
form["formcontrol"]
-------------------
RadioNodeList
2
button
text
-------------------
form["one"]
-------------------
HTMLInputElement
formcontrol
button
-------------------
form["two"]
-------------------
HTMLInputElement
formcontrol
text
-------------------
form["nomatch"]
-------------------
undefined
-------------------
form.formcontrol
-------------------
RadioNodeList
2
button
text
-------------------
form.one
-------------------
HTMLInputElement
formcontrol
button
-------------------
form.two
-------------------
HTMLInputElement
formcontrol
text
-------------------
form.nomatch
-------------------
undefined
-------------------
form[0]
-------------------
HTMLInputElement
formcontrol
button
-------------------
form[1]
-------------------
HTMLInputElement
formcontrol
text
-------------------
form[2]
-------------------
undefined

View file

@ -1,24 +1,57 @@
<form> <form>
<input name="one" id="my-form-control" type="button" /> <input name="one" id="formcontrol" type="button" />
<input name="two" id="my-form-control" type="text" /> <input name="two" id="formcontrol" type="text" />
</form> </form>
<script src="include.js"></script> <script src="include.js"></script>
<script> <script>
test(() => { function printDescription(name) {
const formElements = document.forms[0].elements; println("-------------------");
const radioNodeList = formElements.namedItem("my-form-control"); println(name);
println("-------------------");
}
println(formElements.constructor.name); function dumpInput(name, item) {
printDescription(name);
println(item.constructor.name);
println(item.id);
println(item.type);
}
function dumpRadioNodeList(name, radioNodeList) {
printDescription(name);
println(radioNodeList.constructor.name); println(radioNodeList.constructor.name);
println(radioNodeList.length); println(radioNodeList.length);
println(radioNodeList[0].type); println(radioNodeList[0].type);
println(radioNodeList[1].type); println(radioNodeList[1].type);
}
const nonMatching = formElements.namedItem("no match"); function dumpNoMatch(name, item) {
println(nonMatching); printDescription(name);
println(item);
}
const singleElement = formElements.namedItem("two"); test(() => {
println(singleElement.constructor.name); const form = document.forms[0].elements;
println(singleElement.type); println(form.constructor.name);
println(form.length);
dumpRadioNodeList('form.namedItem("formcontrol")', form.namedItem("formcontrol"))
dumpInput('form.namedItem("one")', form.namedItem("one"));
dumpInput('form.namedItem("two")', form.namedItem("two"));
dumpNoMatch('form.namedItem("nomatch")', form.namedItem("nomatch"));
dumpRadioNodeList('form["formcontrol"]', form["formcontrol"])
dumpInput('form["one"]', form["one"]);
dumpInput('form["two"]', form["two"]);
dumpNoMatch('form["nomatch"]', form["nomatch"]);
dumpRadioNodeList('form.formcontrol', form.formcontrol)
dumpInput('form.one', form.one);
dumpInput('form.two', form.two);
dumpNoMatch('form.nomatch', form.nomatch);
dumpInput('form[0]', form[0]);
dumpInput('form[1]', form[1]);
dumpNoMatch('form[2]', form[2]);
}) })
</script> </script>

View file

@ -77,4 +77,11 @@ Variant<Empty, Element*, JS::Handle<RadioNodeList>> HTMLFormControlsCollection::
})); }));
} }
WebIDL::ExceptionOr<JS::Value> HTMLFormControlsCollection::named_item_value(FlyString const& name) const
{
return named_item_or_radio_node_list(name).visit(
[](Empty) -> JS::Value { return JS::js_undefined(); },
[](auto const& value) -> JS::Value { return value; });
}
} }

View file

@ -25,6 +25,8 @@ public:
protected: protected:
virtual void initialize(JS::Realm&) override; virtual void initialize(JS::Realm&) override;
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const final;
private: private:
HTMLFormControlsCollection(ParentNode& root, Scope, Function<bool(Element const&)> filter); HTMLFormControlsCollection(ParentNode& root, Scope, Function<bool(Element const&)> filter);
}; };