@@ -176,10 +176,24 @@ bitflags! {
176
176
const HAS_SLOTTED = 1 << 1 ;
177
177
const HAS_PART = 1 << 2 ;
178
178
const HAS_PARENT = 1 << 3 ;
179
+ const HAS_NON_FEATURELESS_COMPONENT = 1 << 4 ;
180
+ const HAS_HOST = 1 << 5 ;
179
181
}
180
182
}
181
183
182
- #[ derive( Clone , Copy , Debug , Eq , PartialEq , ToShmem ) ]
184
+ impl SelectorFlags {
185
+ /// When you nest a pseudo-element with something like:
186
+ ///
187
+ /// ::before { & { .. } }
188
+ ///
189
+ /// It is not supposed to work, because :is(::before) is invalid. We can't propagate the
190
+ /// pseudo-flags from inner to outer selectors, to avoid breaking our invariants.
191
+ pub ( crate ) fn for_nesting ( ) -> Self {
192
+ Self :: all ( ) - ( Self :: HAS_PSEUDO | Self :: HAS_SLOTTED | Self :: HAS_PART )
193
+ }
194
+ }
195
+
196
+ #[ derive( Clone , Copy , Debug , Default , Eq , PartialEq , ToShmem ) ]
183
197
pub struct SpecificityAndFlags {
184
198
/// There are two free bits here, since we use ten bits for each specificity
185
199
/// kind (id, class, element).
@@ -188,33 +202,6 @@ pub struct SpecificityAndFlags {
188
202
pub ( crate ) flags : SelectorFlags ,
189
203
}
190
204
191
- impl SpecificityAndFlags {
192
- #[ inline]
193
- pub fn specificity ( & self ) -> u32 {
194
- self . specificity
195
- }
196
-
197
- #[ inline]
198
- pub fn has_pseudo_element ( & self ) -> bool {
199
- self . flags . intersects ( SelectorFlags :: HAS_PSEUDO )
200
- }
201
-
202
- #[ inline]
203
- pub fn has_parent_selector ( & self ) -> bool {
204
- self . flags . intersects ( SelectorFlags :: HAS_PARENT )
205
- }
206
-
207
- #[ inline]
208
- pub fn is_slotted ( & self ) -> bool {
209
- self . flags . intersects ( SelectorFlags :: HAS_SLOTTED )
210
- }
211
-
212
- #[ inline]
213
- pub fn is_part ( & self ) -> bool {
214
- self . flags . intersects ( SelectorFlags :: HAS_PART )
215
- }
216
- }
217
-
218
205
const MAX_10BIT : u32 = ( 1u32 << 10 ) - 1 ;
219
206
220
207
#[ derive( Add , AddAssign , Clone , Copy , Default , Eq , Ord , PartialEq , PartialOrd ) ]
@@ -276,9 +263,12 @@ where
276
263
flags. insert ( SelectorFlags :: HAS_PSEUDO ) ;
277
264
specificity. element_selectors += 1
278
265
} ,
279
- Component :: LocalName ( ..) => specificity. element_selectors += 1 ,
266
+ Component :: LocalName ( ..) => {
267
+ flags. insert ( SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
268
+ specificity. element_selectors += 1
269
+ } ,
280
270
Component :: Slotted ( ref selector) => {
281
- flags. insert ( SelectorFlags :: HAS_SLOTTED ) ;
271
+ flags. insert ( SelectorFlags :: HAS_SLOTTED | SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
282
272
specificity. element_selectors += 1 ;
283
273
// Note that due to the way ::slotted works we only compete with
284
274
// other ::slotted rules, so the above rule doesn't really
@@ -287,21 +277,19 @@ where
287
277
//
288
278
// See: https://github.com/w3c/csswg-drafts/issues/1915
289
279
* specificity += Specificity :: from ( selector. specificity ( ) ) ;
290
- if selector. has_parent_selector ( ) {
291
- flags. insert ( SelectorFlags :: HAS_PARENT ) ;
292
- }
280
+ flags. insert ( selector. flags ( ) ) ;
293
281
} ,
294
282
Component :: Host ( ref selector) => {
283
+ flags. insert ( SelectorFlags :: HAS_HOST ) ;
295
284
specificity. class_like_selectors += 1 ;
296
285
if let Some ( ref selector) = * selector {
297
286
// See: https://github.com/w3c/csswg-drafts/issues/1915
298
287
* specificity += Specificity :: from ( selector. specificity ( ) ) ;
299
- if selector. has_parent_selector ( ) {
300
- flags. insert ( SelectorFlags :: HAS_PARENT ) ;
301
- }
288
+ flags. insert ( selector. flags ( ) - SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
302
289
}
303
290
} ,
304
291
Component :: ID ( ..) => {
292
+ flags. insert ( SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
305
293
specificity. id_selectors += 1 ;
306
294
} ,
307
295
Component :: Class ( ..) |
@@ -313,6 +301,7 @@ where
313
301
Component :: Scope |
314
302
Component :: Nth ( ..) |
315
303
Component :: NonTSPseudoClass ( ..) => {
304
+ flags. insert ( SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
316
305
specificity. class_like_selectors += 1 ;
317
306
} ,
318
307
Component :: NthOf ( ref nth_of_data) => {
@@ -325,7 +314,7 @@ where
325
314
specificity. class_like_selectors += 1 ;
326
315
let sf = selector_list_specificity_and_flags ( nth_of_data. selectors ( ) . iter ( ) ) ;
327
316
* specificity += Specificity :: from ( sf. specificity ) ;
328
- flags. insert ( sf. flags ) ;
317
+ flags. insert ( sf. flags | SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
329
318
} ,
330
319
// https://drafts.csswg.org/selectors/#specificity-rules:
331
320
//
@@ -344,7 +333,7 @@ where
344
333
Component :: Has ( ref relative_selectors) => {
345
334
let sf = relative_selector_list_specificity_and_flags ( relative_selectors) ;
346
335
* specificity += Specificity :: from ( sf. specificity ) ;
347
- flags. insert ( sf. flags ) ;
336
+ flags. insert ( sf. flags | SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
348
337
} ,
349
338
Component :: ExplicitUniversalType |
350
339
Component :: ExplicitAnyNamespace |
@@ -354,6 +343,7 @@ where
354
343
Component :: RelativeSelectorAnchor |
355
344
Component :: Invalid ( ..) => {
356
345
// Does not affect specificity
346
+ flags. insert ( SelectorFlags :: HAS_NON_FEATURELESS_COMPONENT ) ;
357
347
} ,
358
348
}
359
349
}
@@ -377,9 +367,7 @@ pub(crate) fn selector_list_specificity_and_flags<'a, Impl: SelectorImpl>(
377
367
let mut flags = SelectorFlags :: empty ( ) ;
378
368
for selector in itr {
379
369
specificity = std:: cmp:: max ( specificity, selector. specificity ( ) ) ;
380
- if selector. has_parent_selector ( ) {
381
- flags. insert ( SelectorFlags :: HAS_PARENT ) ;
382
- }
370
+ flags. insert ( selector. flags ( ) ) ;
383
371
}
384
372
SpecificityAndFlags { specificity, flags }
385
373
}
0 commit comments