diff --git a/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Libraries/LibWeb/HTML/HTMLSelectElement.cpp index 42070623503..34207d6c88d 100644 --- a/Libraries/LibWeb/HTML/HTMLSelectElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLSelectElement.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2020, the SerenityOS developers. * Copyright (c) 2021-2022, Andreas Kling * Copyright (c) 2023, Bastiaan van der Plaat + * Copyright (c) 2025, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -292,9 +293,36 @@ i32 HTMLSelectElement::default_tab_index_value() const return 0; } +bool HTMLSelectElement::can_skip_children_changed_selectedness_update(ChildrenChangedMetadata const& metadata) const +{ + // If the following criteria are met, there is no need to re-run the selectedness algorithm. + // FIXME: We can tighten up these conditions and skip even more work! + if (metadata.type != ChildrenChangedMetadata::Type::Inserted) + return false; + + if (auto* option = as_if(*metadata.node)) { + if (option->selected()) + return false; + + if (m_cached_number_of_selected_options >= 2) + return false; + + if (display_size() == 1 && m_cached_number_of_selected_options == 0) + return false; + + return true; + } + + return false; +} + void HTMLSelectElement::children_changed(ChildrenChangedMetadata const* metadata) { Base::children_changed(metadata); + + if (metadata && can_skip_children_changed_selectedness_update(*metadata)) + return; + update_cached_list_of_options(); update_selectedness(); } diff --git a/Libraries/LibWeb/HTML/HTMLSelectElement.h b/Libraries/LibWeb/HTML/HTMLSelectElement.h index 9f563200acf..ddea134edaf 100644 --- a/Libraries/LibWeb/HTML/HTMLSelectElement.h +++ b/Libraries/LibWeb/HTML/HTMLSelectElement.h @@ -110,6 +110,7 @@ private: virtual void computed_properties_changed() override; virtual void children_changed(ChildrenChangedMetadata const*) override; + bool can_skip_children_changed_selectedness_update(ChildrenChangedMetadata const& metadata) const; void update_cached_list_of_options() const; void show_the_picker_if_applicable();