Skip to content

Commit

Permalink
LibWeb: Add support for indexed setter of HTMLOptionsCollection
Browse files Browse the repository at this point in the history
  • Loading branch information
vpzomtrrfrt committed Jul 14, 2024
1 parent 9ce727d commit 875b67a
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Tests/LibWeb/Ref/options-set-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<link rel="match" href="reference/options-set-index.html" />
<select id="select"></select>
<script>
const select = document.getElementById("select");
select.options[0] = new Option("text");
select.value = "text";
</script>
1 change: 1 addition & 0 deletions Tests/LibWeb/Ref/reference/options-set-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<select><option>text</option></select>
48 changes: 48 additions & 0 deletions Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ JS::NonnullGCPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(DOM::Paren
HTMLOptionsCollection::HTMLOptionsCollection(DOM::ParentNode& root, Function<bool(DOM::Element const&)> filter)
: DOM::HTMLCollection(root, Scope::Descendants, move(filter))
{
m_legacy_platform_object_flags->has_indexed_property_setter = true;
m_legacy_platform_object_flags->indexed_property_setter_has_identifier = true;
}

HTMLOptionsCollection::~HTMLOptionsCollection() = default;
Expand Down Expand Up @@ -71,6 +73,52 @@ WebIDL::ExceptionOr<void> HTMLOptionsCollection::set_length(WebIDL::UnsignedLong
return {};
}

// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmloptionscollection-setter
WebIDL::ExceptionOr<void> HTMLOptionsCollection::set_value_of_indexed_property(u32 index, JS::Value unconverted_option)
{
// The spec doesn't seem to require this, but it's consistent with length handling and other browsers
if (index > 100'000) {
return {};
}

// 1. If value is null, invoke the steps for the remove method with index as the argument, and return.
if (unconverted_option.is_null()) {
remove(static_cast<WebIDL::Long>(index));
return {};
}

if (!unconverted_option.is_object() || !is<HTMLOptionElement>(unconverted_option.as_object())) {
return WebIDL::TypeMismatchError::create(realm(), "The value provided is not an HTMLOptionElement"_fly_string);
}

auto& option = dynamic_cast<HTMLOptionElement&>(unconverted_option.as_object());

// 2. Let length be the number of nodes represented by the collection.
auto length = this->length();

auto root_element = root();

if (index >= length) {
// 3. Let n be index minus length.
auto n = index - length;

// 4. If n is greater than zero, then append a DocumentFragment consisting of n-1 new option elements with no attributes and no child nodes to the select element on which the HTMLOptionsCollection is rooted.
if (n > 0) {
for (WebIDL::UnsignedLong i = 0; i < n - 1; i++) {
TRY(root_element->append_child(TRY(DOM::create_element(root_element->document(), HTML::TagNames::option, Namespace::HTML))));
}
}

// 5. If n is greater than or equal to zero, append value to the select element.
TRY(root_element->append_child(option));
} else {
// 5 (cont). Otherwise, replace the indexth element in the collection by value.
TRY(root_element->replace_child(option, *item(index)));
}

return {};
}

// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmloptionscollection-add
WebIDL::ExceptionOr<void> HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement element, Optional<HTMLElementOrElementIndex> before)
{
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class HTMLOptionsCollection final : public DOM::HTMLCollection {
[[nodiscard]] static JS::NonnullGCPtr<HTMLOptionsCollection> create(DOM::ParentNode& root, ESCAPING Function<bool(DOM::Element const&)> filter);
virtual ~HTMLOptionsCollection() override;

WebIDL::ExceptionOr<void> set_value_of_indexed_property(u32, JS::Value) override;

WebIDL::ExceptionOr<void> set_length(WebIDL::UnsignedLong);

WebIDL::ExceptionOr<void> add(HTMLOptionOrOptGroupElement element, Optional<HTMLElementOrElementIndex> before = {});
Expand Down

0 comments on commit 875b67a

Please sign in to comment.