1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 //! Helper module to build up a selector safely and efficiently.
6 //!
7 //! Our selector representation is designed to optimize matching, and has
8 //! several requirements:
9 //! * All simple selectors and combinators are stored inline in the same buffer
10 //!   as Component instances.
11 //! * We store the top-level compound selectors from right to left, i.e. in
12 //!   matching order.
13 //! * We store the simple selectors for each combinator from left to right, so
14 //!   that we match the cheaper simple selectors first.
15 //!
16 //! Meeting all these constraints without extra memmove traffic during parsing
17 //! is non-trivial. This module encapsulates those details and presents an
18 //! easy-to-use API for the parser.
19 
20 use parser::{Combinator, Component, SelectorImpl};
21 use servo_arc::{Arc, HeaderWithLength, ThinArc};
22 use sink::Push;
23 use smallvec::{self, SmallVec};
24 use std::cmp;
25 use std::iter;
26 use std::ops::Add;
27 use std::ptr;
28 use std::slice;
29 
30 /// Top-level SelectorBuilder struct. This should be stack-allocated by the
31 /// consumer and never moved (because it contains a lot of inline data that
32 /// would be slow to memmov).
33 ///
34 /// After instantation, callers may call the push_simple_selector() and
35 /// push_combinator() methods to append selector data as it is encountered
36 /// (from left to right). Once the process is complete, callers should invoke
37 /// build(), which transforms the contents of the SelectorBuilder into a heap-
38 /// allocated Selector and leaves the builder in a drained state.
39 pub struct SelectorBuilder<Impl: SelectorImpl> {
40     /// The entire sequence of simple selectors, from left to right, without combinators.
41     ///
42     /// We make this large because the result of parsing a selector is fed into a new
43     /// Arc-ed allocation, so any spilled vec would be a wasted allocation. Also,
44     /// Components are large enough that we don't have much cache locality benefit
45     /// from reserving stack space for fewer of them.
46     simple_selectors: SmallVec<[Component<Impl>; 32]>,
47     /// The combinators, and the length of the compound selector to their left.
48     combinators: SmallVec<[(Combinator, usize); 16]>,
49     /// The length of the current compount selector.
50     current_len: usize,
51 }
52 
53 impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
54     #[inline(always)]
default() -> Self55     fn default() -> Self {
56         SelectorBuilder {
57             simple_selectors: SmallVec::new(),
58             combinators: SmallVec::new(),
59             current_len: 0,
60         }
61     }
62 }
63 
64 impl<Impl: SelectorImpl> Push<Component<Impl>> for SelectorBuilder<Impl> {
push(&mut self, value: Component<Impl>)65     fn push(&mut self, value: Component<Impl>) {
66         self.push_simple_selector(value);
67     }
68 }
69 
70 impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
71     /// Pushes a simple selector onto the current compound selector.
72     #[inline(always)]
push_simple_selector(&mut self, ss: Component<Impl>)73     pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
74         debug_assert!(!ss.is_combinator());
75         self.simple_selectors.push(ss);
76         self.current_len += 1;
77     }
78 
79     /// Completes the current compound selector and starts a new one, delimited
80     /// by the given combinator.
81     #[inline(always)]
push_combinator(&mut self, c: Combinator)82     pub fn push_combinator(&mut self, c: Combinator) {
83         self.combinators.push((c, self.current_len));
84         self.current_len = 0;
85     }
86 
87     /// Returns true if no simple selectors have ever been pushed to this builder.
88     #[inline(always)]
is_empty(&self) -> bool89     pub fn is_empty(&self) -> bool {
90         self.simple_selectors.is_empty()
91     }
92 
93     /// Returns true if combinators have ever been pushed to this builder.
94     #[inline(always)]
has_combinators(&self) -> bool95     pub fn has_combinators(&self) -> bool {
96         !self.combinators.is_empty()
97     }
98 
99     /// Consumes the builder, producing a Selector.
100     #[inline(always)]
build( &mut self, parsed_pseudo: bool, parsed_slotted: bool, ) -> ThinArc<SpecificityAndFlags, Component<Impl>>101     pub fn build(
102         &mut self,
103         parsed_pseudo: bool,
104         parsed_slotted: bool,
105     ) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
106         // Compute the specificity and flags.
107         let mut spec = SpecificityAndFlags(specificity(self.simple_selectors.iter()));
108         if parsed_pseudo {
109             spec.0 |= HAS_PSEUDO_BIT;
110         }
111 
112         if parsed_slotted {
113             spec.0 |= HAS_SLOTTED_BIT;
114         }
115 
116         self.build_with_specificity_and_flags(spec)
117     }
118 
119 
120     /// Builds with an explicit SpecificityAndFlags. This is separated from build() so
121     /// that unit tests can pass an explicit specificity.
122     #[inline(always)]
build_with_specificity_and_flags(&mut self, spec: SpecificityAndFlags) -> ThinArc<SpecificityAndFlags, Component<Impl>>123     pub fn build_with_specificity_and_flags(&mut self, spec: SpecificityAndFlags)
124                                             -> ThinArc<SpecificityAndFlags, Component<Impl>> {
125         // First, compute the total number of Components we'll need to allocate
126         // space for.
127         let full_len = self.simple_selectors.len() + self.combinators.len();
128 
129         // Create the header.
130         let header = HeaderWithLength::new(spec, full_len);
131 
132         // Create the Arc using an iterator that drains our buffers.
133 
134         // Use a raw pointer to be able to call set_len despite "borrowing" the slice.
135         // This is similar to SmallVec::drain, but we use a slice here because
136         // we’re gonna traverse it non-linearly.
137         let raw_simple_selectors: *const [Component<Impl>] = &*self.simple_selectors;
138         unsafe {
139             // Panic-safety: if SelectorBuilderIter is not iterated to the end,
140             // some simple selectors will safely leak.
141             self.simple_selectors.set_len(0)
142         }
143         let (rest, current) = split_from_end(unsafe { &*raw_simple_selectors }, self.current_len);
144         let iter = SelectorBuilderIter {
145             current_simple_selectors: current.iter(),
146             rest_of_simple_selectors: rest,
147             combinators: self.combinators.drain().rev(),
148         };
149 
150         Arc::into_thin(Arc::from_header_and_iter(header, iter))
151     }
152 }
153 
154 struct SelectorBuilderIter<'a, Impl: SelectorImpl> {
155     current_simple_selectors: slice::Iter<'a, Component<Impl>>,
156     rest_of_simple_selectors: &'a [Component<Impl>],
157     combinators: iter::Rev<smallvec::Drain<'a, (Combinator, usize)>>,
158 }
159 
160 impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> {
len(&self) -> usize161     fn len(&self) -> usize {
162         self.current_simple_selectors.len() +
163         self.rest_of_simple_selectors.len() +
164         self.combinators.len()
165     }
166 }
167 
168 impl<'a, Impl: SelectorImpl> Iterator for SelectorBuilderIter<'a, Impl> {
169     type Item = Component<Impl>;
170     #[inline(always)]
next(&mut self) -> Option<Self::Item>171     fn next(&mut self) -> Option<Self::Item> {
172         if let Some(simple_selector_ref) = self.current_simple_selectors.next() {
173             // Move a simple selector out of this slice iterator.
174             // This is safe because we’ve called SmallVec::set_len(0) above,
175             // so SmallVec::drop won’t drop this simple selector.
176             unsafe {
177                 Some(ptr::read(simple_selector_ref))
178             }
179         } else {
180             self.combinators.next().map(|(combinator, len)| {
181                 let (rest, current) = split_from_end(self.rest_of_simple_selectors, len);
182                 self.rest_of_simple_selectors = rest;
183                 self.current_simple_selectors = current.iter();
184                 Component::Combinator(combinator)
185             })
186         }
187     }
188 
size_hint(&self) -> (usize, Option<usize>)189     fn size_hint(&self) -> (usize, Option<usize>) {
190         (self.len(), Some(self.len()))
191     }
192 }
193 
split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T])194 fn split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T]) {
195     s.split_at(s.len() - at)
196 }
197 
198 pub const HAS_PSEUDO_BIT: u32 = 1 << 30;
199 pub const HAS_SLOTTED_BIT: u32 = 1 << 31;
200 
201 /// We use ten bits for each specificity kind (id, class, element), and the two
202 /// high bits for the pseudo and slotted flags.
203 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
204 pub struct SpecificityAndFlags(pub u32);
205 
206 impl SpecificityAndFlags {
207     #[inline]
specificity(&self) -> u32208     pub fn specificity(&self) -> u32 {
209         self.0 & !(HAS_PSEUDO_BIT | HAS_SLOTTED_BIT)
210     }
211 
212     #[inline]
has_pseudo_element(&self) -> bool213     pub fn has_pseudo_element(&self) -> bool {
214         (self.0 & HAS_PSEUDO_BIT) != 0
215     }
216 
217     #[inline]
is_slotted(&self) -> bool218     pub fn is_slotted(&self) -> bool {
219         (self.0 & HAS_SLOTTED_BIT) != 0
220     }
221 }
222 
223 const MAX_10BIT: u32 = (1u32 << 10) - 1;
224 
225 #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
226 struct Specificity {
227     id_selectors: u32,
228     class_like_selectors: u32,
229     element_selectors: u32,
230 }
231 
232 impl Add for Specificity {
233     type Output = Specificity;
234 
add(self, rhs: Specificity) -> Specificity235     fn add(self, rhs: Specificity) -> Specificity {
236         Specificity {
237             id_selectors: self.id_selectors + rhs.id_selectors,
238             class_like_selectors:
239                 self.class_like_selectors + rhs.class_like_selectors,
240             element_selectors:
241                 self.element_selectors + rhs.element_selectors,
242         }
243     }
244 }
245 
246 impl Default for Specificity {
default() -> Specificity247     fn default() -> Specificity {
248         Specificity {
249             id_selectors: 0,
250             class_like_selectors: 0,
251             element_selectors: 0,
252         }
253     }
254 }
255 
256 impl From<u32> for Specificity {
from(value: u32) -> Specificity257     fn from(value: u32) -> Specificity {
258         assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
259         Specificity {
260             id_selectors: value >> 20,
261             class_like_selectors: (value >> 10) & MAX_10BIT,
262             element_selectors: value & MAX_10BIT,
263         }
264     }
265 }
266 
267 impl From<Specificity> for u32 {
from(specificity: Specificity) -> u32268     fn from(specificity: Specificity) -> u32 {
269         cmp::min(specificity.id_selectors, MAX_10BIT) << 20
270         | cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10
271         | cmp::min(specificity.element_selectors, MAX_10BIT)
272     }
273 }
274 
specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> u32 where Impl: SelectorImpl275 fn specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> u32
276     where Impl: SelectorImpl
277 {
278     complex_selector_specificity(iter).into()
279 }
280 
complex_selector_specificity<Impl>(mut iter: slice::Iter<Component<Impl>>) -> Specificity where Impl: SelectorImpl281 fn complex_selector_specificity<Impl>(mut iter: slice::Iter<Component<Impl>>)
282                                       -> Specificity
283     where Impl: SelectorImpl
284 {
285     fn simple_selector_specificity<Impl>(
286         simple_selector: &Component<Impl>,
287         specificity: &mut Specificity,
288     )
289     where
290         Impl: SelectorImpl
291     {
292         match *simple_selector {
293             Component::Combinator(..) => unreachable!(),
294             // FIXME(emilio): Spec doesn't define any particular specificity for
295             // ::slotted(), so apply the general rule for pseudos per:
296             //
297             // https://github.com/w3c/csswg-drafts/issues/1915
298             //
299             // Though other engines compute it dynamically, so maybe we should
300             // do that instead, eventually.
301             Component::Slotted(..) |
302             Component::PseudoElement(..) |
303             Component::LocalName(..) => {
304                 specificity.element_selectors += 1
305             }
306             Component::ID(..) => {
307                 specificity.id_selectors += 1
308             }
309             Component::Class(..) |
310             Component::AttributeInNoNamespace { .. } |
311             Component::AttributeInNoNamespaceExists { .. } |
312             Component::AttributeOther(..) |
313 
314             Component::FirstChild | Component::LastChild |
315             Component::OnlyChild | Component::Root |
316             Component::Empty | Component::Scope |
317             Component::NthChild(..) |
318             Component::NthLastChild(..) |
319             Component::NthOfType(..) |
320             Component::NthLastOfType(..) |
321             Component::FirstOfType | Component::LastOfType |
322             Component::OnlyOfType |
323             Component::NonTSPseudoClass(..) => {
324                 specificity.class_like_selectors += 1
325             }
326             Component::ExplicitUniversalType |
327             Component::ExplicitAnyNamespace |
328             Component::ExplicitNoNamespace |
329             Component::DefaultNamespace(..) |
330             Component::Namespace(..) => {
331                 // Does not affect specificity
332             }
333             Component::Negation(ref negated) => {
334                 for ss in negated.iter() {
335                     simple_selector_specificity(&ss, specificity);
336                 }
337             }
338         }
339     }
340 
341     let mut specificity = Default::default();
342     for simple_selector in &mut iter {
343         simple_selector_specificity(&simple_selector, &mut specificity);
344     }
345     specificity
346 }
347