summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/CSS
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2023-03-30 11:18:50 +0200
committerAndreas Kling <kling@serenityos.org>2023-03-30 14:12:07 +0200
commit1f166b3a15b38e1ee065905d4e99401ba39b9f8e (patch)
treef1189093bba2c2d2d0cc6db5fae4838d6af65b59 /Userland/Libraries/LibWeb/CSS
parentd4b2544dc55785f7233f84943ae579be31e43e5e (diff)
downloadserenity-1f166b3a15b38e1ee065905d4e99401ba39b9f8e.zip
LibWeb: Don't re-sort StyleSheetList on every new sheet insertion
This was causing a huge slowdown when loading some pages with weirdly huge number of style sheets. For example, amazon.com has over 200 style elements, which meant we had to resort the StyleSheetList 200 times. (And sorting itself was slow because it has to compare DOM positions.) Instead of sorting, we now look for the correct insertion point when adding new style sheets, and we start the search from the end, which is where style sheets are typically added in the vast majority of cases. This removes a 600ms time sink when loading Amazon on my machine! :^)
Diffstat (limited to 'Userland/Libraries/LibWeb/CSS')
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp
index 8c0abc6dcc..2ba3d57c92 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp
@@ -15,9 +15,25 @@ namespace Web::CSS {
void StyleSheetList::add_sheet(CSSStyleSheet& sheet)
{
sheet.set_style_sheet_list({}, this);
- m_sheets.append(sheet);
- sort_sheets();
+ if (m_sheets.is_empty()) {
+ // This is the first sheet, append it to the list.
+ m_sheets.append(sheet);
+ } else {
+ // We have sheets from before. Insert the new sheet in the correct position (DOM tree order).
+ bool did_insert = false;
+ for (ssize_t i = m_sheets.size() - 1; i >= 0; --i) {
+ auto& existing_sheet = *m_sheets[i];
+ auto position = existing_sheet.owner_node()->compare_document_position(sheet.owner_node());
+ if (position & DOM::Node::DocumentPosition::DOCUMENT_POSITION_FOLLOWING) {
+ m_sheets.insert(i + 1, sheet);
+ did_insert = true;
+ break;
+ }
+ }
+ if (!did_insert)
+ m_sheets.prepend(sheet);
+ }
if (sheet.rules().length() == 0) {
// NOTE: If the added sheet has no rules, we don't have to invalidate anything.