aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/shadowroot.rs
diff options
context:
space:
mode:
authorSimon Wülker <simon.wuelker@arcor.de>2025-03-11 00:11:20 +0100
committerGitHub <noreply@github.com>2025-03-10 23:11:20 +0000
commitfd0e2125c60506fea5408b34a0c2021b8ca7bf00 (patch)
tree7e8dac6454c4a52857e727420fdd8b3361b2c7c2 /components/script/dom/shadowroot.rs
parent0419a7818dc051aef9f0bb9022ee89aaa4183b99 (diff)
downloadservo-fd0e2125c60506fea5408b34a0c2021b8ca7bf00.tar.gz
servo-fd0e2125c60506fea5408b34a0c2021b8ca7bf00.zip
Keep a list of slot descendants on each shadow root (#35802)
This makes it much faster to traverse over the slot descendants of a shadow root, which is a fairly costly part of "assign slottables to a tree". This reduces the time it takes for the results to load on wpt.fyi from over 3 minutes to about 5 seconds. Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Diffstat (limited to 'components/script/dom/shadowroot.rs')
-rw-r--r--components/script/dom/shadowroot.rs43
1 files changed, 43 insertions, 0 deletions
diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs
index 357594a0948..c1adb60f566 100644
--- a/components/script/dom/shadowroot.rs
+++ b/components/script/dom/shadowroot.rs
@@ -2,6 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use std::collections::HashMap;
+use std::collections::hash_map::Entry;
+
use dom_struct::dom_struct;
use servo_arc::Arc;
use servo_atoms::Atom;
@@ -13,6 +16,7 @@ use style::stylist::{CascadeData, Stylist};
use crate::conversions::Convert;
use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::HTMLSlotElementBinding::HTMLSlotElement_Binding::HTMLSlotElementMethods;
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods;
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
ShadowRootMode, SlotAssignmentMode,
@@ -27,8 +31,10 @@ use crate::dom::document::Document;
use crate::dom::documentfragment::DocumentFragment;
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, StyleSheetInDocument};
use crate::dom::element::Element;
+use crate::dom::htmlslotelement::HTMLSlotElement;
use crate::dom::node::{
BindContext, Node, NodeDamage, NodeFlags, NodeTraits, ShadowIncluding, UnbindContext,
+ VecPreOrderInsertionHelper,
};
use crate::dom::stylesheetlist::{StyleSheetList, StyleSheetListOwner};
use crate::dom::types::EventTarget;
@@ -65,6 +71,8 @@ pub(crate) struct ShadowRoot {
/// <https://dom.spec.whatwg.org/#dom-shadowroot-clonable>
clonable: bool,
+
+ slots: DomRefCell<HashMap<DOMString, Vec<Dom<HTMLSlotElement>>>>,
}
impl ShadowRoot {
@@ -95,6 +103,7 @@ impl ShadowRoot {
mode,
slot_assignment_mode,
clonable,
+ slots: Default::default(),
}
}
@@ -209,6 +218,40 @@ impl ShadowRoot {
root,
);
}
+
+ pub(crate) fn register_slot(&self, slot: &HTMLSlotElement) {
+ debug!("Registering slot with name={:?}", slot.Name().str());
+
+ let mut slots = self.slots.borrow_mut();
+
+ let slots_with_the_same_name = slots.entry(slot.Name()).or_default();
+
+ // Insert the slot before the first element that comes after it in tree order
+ slots_with_the_same_name.insert_pre_order(slot, self.upcast::<Node>());
+ }
+
+ pub(crate) fn unregister_slot(&self, name: DOMString, slot: &HTMLSlotElement) {
+ debug!("Unregistering slot with name={:?}", name.str());
+
+ let mut slots = self.slots.borrow_mut();
+ let Entry::Occupied(mut entry) = slots.entry(name) else {
+ panic!("slot is not registered");
+ };
+ entry.get_mut().retain(|s| slot != &**s);
+ }
+
+ /// Find the first slot with the given name among this root's descendants in tree order
+ pub(crate) fn slot_for_name(&self, name: &DOMString) -> Option<DomRoot<HTMLSlotElement>> {
+ self.slots
+ .borrow()
+ .get(name)
+ .and_then(|slots| slots.first())
+ .map(|slot| slot.as_rooted())
+ }
+
+ pub(crate) fn has_slot_descendants(&self) -> bool {
+ !self.slots.borrow().is_empty()
+ }
}
impl ShadowRootMethods<crate::DomTypeHolder> for ShadowRoot {