commit 04b013b47241e496684d5f7eb4368c0898166d87
parent cfbe87ee22857758128bf11690eb33f7c6662a18
Author: Denis Palmeiro <dpalmeiro@mozilla.com>
Date: Tue, 30 Dec 2025 15:43:09 +0000
Bug 2006172: Compare style attributes by value instead of just pointer identity when style sharing. r=emilio,firefox-style-system-reviewers
Inline styles set by JS (i.e. element.style.display = "block") allocate new
PropertyDeclarationBlock pointers causing identical inline styles to have
different pointers.
Differential Revision: https://phabricator.services.mozilla.com/D277605
Diffstat:
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/servo/components/style/properties/declaration_block.rs b/servo/components/style/properties/declaration_block.rs
@@ -261,6 +261,15 @@ pub struct PropertyDeclarationBlock {
property_ids: PropertyDeclarationIdSet,
}
+impl PartialEq for PropertyDeclarationBlock {
+ fn eq(&self, other: &Self) -> bool {
+ // property_ids must be equal if declarations are equal, so we don't
+ // need to compare them explicitly.
+ self.declarations == other.declarations
+ && self.declarations_importance == other.declarations_importance
+ }
+}
+
/// Iterator over `(PropertyDeclaration, Importance)` pairs.
pub struct DeclarationImportanceIterator<'a> {
iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
diff --git a/servo/components/style/sharing/checks.rs b/servo/components/style/sharing/checks.rs
@@ -53,10 +53,13 @@ where
true
}
-/// Whether two elements have the same same style attribute (by pointer identity).
+/// Whether two elements have the same style attribute.
+///
+/// First checks pointer identity (fast path), then falls back to value comparison.
pub fn have_same_style_attribute<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
+ shared_context: &SharedStyleContext,
) -> bool
where
E: TElement,
@@ -64,7 +67,13 @@ where
match (target.style_attribute(), candidate.style_attribute()) {
(None, None) => true,
(Some(_), None) | (None, Some(_)) => false,
- (Some(a), Some(b)) => &*a as *const _ == &*b as *const _,
+ (Some(a), Some(b)) => {
+ if std::ptr::eq(&*a, &*b) {
+ return true;
+ }
+ let guard = shared_context.guards.author;
+ *a.read_with(guard) == *b.read_with(guard)
+ },
}
}
diff --git a/servo/components/style/sharing/mod.rs b/servo/components/style/sharing/mod.rs
@@ -847,7 +847,7 @@ impl<E: TElement> StyleSharingCache<E> {
return None;
}
- if !checks::have_same_style_attribute(target, candidate) {
+ if !checks::have_same_style_attribute(target, candidate, shared_context) {
trace!("Miss: Style Attr");
return None;
}