Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp (C++)

Code before:
    }

    // 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"_utf16);
    }

    auto& option = static_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)
{
    auto resolved_element = element.visit(
        [](auto& e) -> GC::Root<HTMLElement> {
            return GC::make_root(static_cast<HTML::HTMLElement&>(*e));
        });

    GC::Ptr<DOM::Node> before_element;
    if (before.has_value() && before->has<GC::Root<HTMLElement>>())
        before_element = before->get<GC::Root<HTMLElement>>().ptr();

Review comment (suggestion):
This does not match the spec. For example, if `n == 1`, we should append `n - 1 -> 0` new option elements. You're now appending a single option element instead.

Code after:
    }

    // 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"_utf16);
    }

    auto& option = static_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();

    // 3. Let delta be index minus length
    auto delta = static_cast<i64>(index) - static_cast<i64>(length);

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

    // 5. If delta is greater than or equal to zero, append value to the select element. Otherwise, replace the indexth
    //    element in the collection by value.
    if (delta >= 0) {
        TRY(root_element->append_child(option));
    } else {
        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)
{
    auto resolved_element = element.visit(
        [](auto& e) -> GC::Root<HTMLElement> {
            return GC::make_root(static_cast<HTML::HTMLElement&>(*e));
        });

    GC::Ptr<DOM::Node> before_element;
    if (before.has_value() && before->has<GC::Root<HTMLElement>>())