Skip to content

Commit 178939d

Browse files
heycamemilio
authored andcommitted
style: Record in RestyleHints how far down the tree selector matching must be re-run.
1 parent a397590 commit 178939d

File tree

1 file changed

+100
-34
lines changed

1 file changed

+100
-34
lines changed

components/style/restyle_hints.rs

+100-34
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,8 @@ use stylist::SelectorMap;
3737
/// unnecessary.
3838
#[derive(Debug, Clone, PartialEq)]
3939
pub struct RestyleHint {
40-
/// Rerun selector matching on the element.
41-
match_self: bool,
42-
43-
/// Rerun selector matching on all of the element's descendants.
44-
match_descendants: bool,
40+
/// Depths at which selector matching must be re-run.
41+
match_under_self: RestyleDepths,
4542

4643
/// Rerun selector matching on all later siblings of the element and all
4744
/// of their descendants.
@@ -82,6 +79,75 @@ bitflags! {
8279
}
8380
}
8481

82+
/// Eight bit wide bitfield representing depths of a DOM subtree's descendants,
83+
/// used to represent which elements must have selector matching re-run on them.
84+
///
85+
/// The least significant bit indicates that selector matching must be re-run
86+
/// for the element itself, the second least significant bit for the element's
87+
/// children, the third its grandchildren, and so on. If the most significant
88+
/// bit it set, it indicates that that selector matching must be re-run for
89+
/// elements at that depth and all of their descendants.
90+
#[derive(Debug, Clone, Copy, PartialEq)]
91+
struct RestyleDepths(u8);
92+
93+
impl RestyleDepths {
94+
/// Returns a `RestyleDepths` representing no element depths.
95+
fn empty() -> Self {
96+
RestyleDepths(0)
97+
}
98+
99+
/// Returns a `RestyleDepths` representing the current element depth.
100+
fn for_self() -> Self {
101+
RestyleDepths(0x01)
102+
}
103+
104+
/// Returns a `RestyleDepths` representing the depths of all descendants of
105+
/// the current element.
106+
fn for_descendants() -> Self {
107+
RestyleDepths(0xfe)
108+
}
109+
110+
/// Returns a `RestyleDepths` representing the current element depth and the
111+
/// depths of all the current element's descendants.
112+
fn for_self_and_descendants() -> Self {
113+
RestyleDepths(0xff)
114+
}
115+
116+
/// Returns whether this `RestyleDepths` represents the current element
117+
/// depth and the depths of all the current element's descendants.
118+
fn is_self_and_descendants(&self) -> bool {
119+
self.0 == 0xff
120+
}
121+
122+
/// Returns whether this `RestyleDepths` includes any element depth.
123+
fn is_any(&self) -> bool {
124+
self.0 != 0
125+
}
126+
127+
/// Returns whether this `RestyleDepths` includes the current element depth.
128+
fn has_self(&self) -> bool {
129+
(self.0 & 0x01) != 0
130+
}
131+
132+
/// Returns a new `RestyleDepths` with all depth values represented by this
133+
/// `RestyleDepths` reduced by one.
134+
fn propagate(&self) -> Self {
135+
RestyleDepths((self.0 >> 1) | (self.0 & 0x80))
136+
}
137+
138+
/// Returns a new `RestyleDepths` that represents the union of the depths
139+
/// from `self` and `other`.
140+
fn insert(&mut self, other: RestyleDepths) {
141+
self.0 |= other.0;
142+
}
143+
144+
/// Returns whether this `RestyleDepths` includes all depths represented
145+
/// by `other`.
146+
fn contains(&self, other: RestyleDepths) -> bool {
147+
(self.0 & other.0) == other.0
148+
}
149+
}
150+
85151
/// Asserts that all RestyleReplacements have a matching nsRestyleHint value.
86152
#[cfg(feature = "gecko")]
87153
#[inline]
@@ -116,8 +182,7 @@ impl RestyleHint {
116182
#[inline]
117183
pub fn empty() -> Self {
118184
RestyleHint {
119-
match_self: false,
120-
match_descendants: false,
185+
match_under_self: RestyleDepths::empty(),
121186
match_later_siblings: false,
122187
replacements: RestyleReplacements::empty(),
123188
}
@@ -128,8 +193,7 @@ impl RestyleHint {
128193
#[inline]
129194
pub fn for_self() -> Self {
130195
RestyleHint {
131-
match_self: true,
132-
match_descendants: false,
196+
match_under_self: RestyleDepths::for_self(),
133197
match_later_siblings: false,
134198
replacements: RestyleReplacements::empty(),
135199
}
@@ -140,8 +204,7 @@ impl RestyleHint {
140204
#[inline]
141205
pub fn descendants() -> Self {
142206
RestyleHint {
143-
match_self: false,
144-
match_descendants: true,
207+
match_under_self: RestyleDepths::for_descendants(),
145208
match_later_siblings: false,
146209
replacements: RestyleReplacements::empty(),
147210
}
@@ -152,8 +215,7 @@ impl RestyleHint {
152215
#[inline]
153216
pub fn later_siblings() -> Self {
154217
RestyleHint {
155-
match_self: false,
156-
match_descendants: false,
218+
match_under_self: RestyleDepths::empty(),
157219
match_later_siblings: true,
158220
replacements: RestyleReplacements::empty(),
159221
}
@@ -164,8 +226,7 @@ impl RestyleHint {
164226
#[inline]
165227
pub fn subtree() -> Self {
166228
RestyleHint {
167-
match_self: true,
168-
match_descendants: true,
229+
match_under_self: RestyleDepths::for_self_and_descendants(),
169230
match_later_siblings: false,
170231
replacements: RestyleReplacements::empty(),
171232
}
@@ -177,8 +238,7 @@ impl RestyleHint {
177238
#[inline]
178239
pub fn subtree_and_later_siblings() -> Self {
179240
RestyleHint {
180-
match_self: true,
181-
match_descendants: true,
241+
match_under_self: RestyleDepths::for_self_and_descendants(),
182242
match_later_siblings: true,
183243
replacements: RestyleReplacements::empty(),
184244
}
@@ -189,8 +249,7 @@ impl RestyleHint {
189249
#[inline]
190250
pub fn for_replacements(replacements: RestyleReplacements) -> Self {
191251
RestyleHint {
192-
match_self: false,
193-
match_descendants: false,
252+
match_under_self: RestyleDepths::empty(),
194253
match_later_siblings: false,
195254
replacements: replacements,
196255
}
@@ -206,14 +265,16 @@ impl RestyleHint {
206265
/// restyle work, and thus any `insert()` calls will have no effect.
207266
#[inline]
208267
pub fn is_maximum(&self) -> bool {
209-
self.match_self && self.match_descendants && self.match_later_siblings && self.replacements.is_all()
268+
self.match_under_self.is_self_and_descendants() &&
269+
self.match_later_siblings &&
270+
self.replacements.is_all()
210271
}
211272

212273
/// Returns whether the hint specifies that some work must be performed on
213274
/// the current element.
214275
#[inline]
215276
pub fn affects_self(&self) -> bool {
216-
self.match_self || !self.replacements.is_empty()
277+
self.match_self() || !self.replacements.is_empty()
217278
}
218279

219280
/// Returns whether the hint specifies that later siblings must be restyled.
@@ -233,25 +294,25 @@ impl RestyleHint {
233294
/// animation cascade level replacement.
234295
#[inline]
235296
pub fn has_non_animation_hint(&self) -> bool {
236-
self.match_self || self.match_descendants || self.match_later_siblings ||
297+
self.match_under_self.is_any() || self.match_later_siblings ||
237298
self.replacements.contains(RESTYLE_STYLE_ATTRIBUTE)
238299
}
239300

240301
/// Returns whether the hint specifies that selector matching must be re-run
241302
/// for the element.
242303
#[inline]
243304
pub fn match_self(&self) -> bool {
244-
self.match_self
305+
self.match_under_self.has_self()
245306
}
246307

247308
/// Returns a new `RestyleHint` appropriate for children of the current
248309
/// element.
249310
#[inline]
250311
pub fn propagate_for_non_animation_restyle(&self) -> Self {
251-
if self.match_descendants {
252-
Self::subtree()
253-
} else {
254-
Self::empty()
312+
RestyleHint {
313+
match_under_self: self.match_under_self.propagate(),
314+
match_later_siblings: false,
315+
replacements: RestyleReplacements::empty(),
255316
}
256317
}
257318

@@ -271,8 +332,7 @@ impl RestyleHint {
271332
/// Unions the specified `RestyleHint` into this one.
272333
#[inline]
273334
pub fn insert_from(&mut self, other: &Self) {
274-
self.match_self |= other.match_self;
275-
self.match_descendants |= other.match_descendants;
335+
self.match_under_self.insert(other.match_under_self);
276336
self.match_later_siblings |= other.match_later_siblings;
277337
self.replacements.insert(other.replacements);
278338
}
@@ -289,9 +349,8 @@ impl RestyleHint {
289349
/// work as the specified one.
290350
#[inline]
291351
pub fn contains(&mut self, other: &Self) -> bool {
292-
!(other.match_self && !self.match_self) &&
293-
!(other.match_descendants && !self.match_descendants) &&
294-
!(other.match_later_siblings && !self.match_later_siblings) &&
352+
self.match_under_self.contains(other.match_under_self) &&
353+
(self.match_later_siblings & other.match_later_siblings) == other.match_later_siblings &&
295354
self.replacements.contains(other.replacements)
296355
}
297356
}
@@ -319,9 +378,16 @@ impl From<nsRestyleHint> for RestyleHint {
319378
use gecko_bindings::structs::nsRestyleHint_eRestyle_SomeDescendants as eRestyle_SomeDescendants;
320379
use gecko_bindings::structs::nsRestyleHint_eRestyle_Subtree as eRestyle_Subtree;
321380

381+
let mut match_under_self = RestyleDepths::empty();
382+
if (raw.0 & (eRestyle_Self.0 | eRestyle_Subtree.0)) != 0 {
383+
match_under_self.insert(RestyleDepths::for_self());
384+
}
385+
if (raw.0 & (eRestyle_Subtree.0 | eRestyle_SomeDescendants.0)) != 0 {
386+
match_under_self.insert(RestyleDepths::for_descendants());
387+
}
388+
322389
RestyleHint {
323-
match_self: (raw.0 & (eRestyle_Self.0 | eRestyle_Subtree.0)) != 0,
324-
match_descendants: (raw.0 & (eRestyle_Subtree.0 | eRestyle_SomeDescendants.0)) != 0,
390+
match_under_self: match_under_self,
325391
match_later_siblings: (raw.0 & eRestyle_LaterSiblings.0) != 0,
326392
replacements: raw.into(),
327393
}

0 commit comments

Comments
 (0)