Skip to content

Commit 7802945

Browse files
committed
Implement zero copy parsing
1 parent 0d2844e commit 7802945

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1542
-1454
lines changed

Cargo.lock

Lines changed: 9 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ parcel_selectors = { version = "0.24.0", path = "./selectors" }
2828
itertools = "0.10.1"
2929
smallvec = { version = "1.7.0", features = ["union"] }
3030
bitflags = "1.3.2"
31-
parcel_sourcemap = "2.0.0"
31+
parcel_sourcemap = "2.0.2"
3232
data-encoding = "2.3.2"
3333
lazy_static = "1.4.0"
3434
clap = { version = "3.0.6", features = ["derive"] }

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,14 @@ console.log(new TextDecoder().decode(code));
142142

143143
```
144144
$ node bench.js bootstrap-4.css
145-
cssnano: 542.956ms
145+
cssnano: 542.879ms
146146
159636 bytes
147147
148-
esbuild: 17.411ms
148+
esbuild: 16.839ms
149149
160332 bytes
150150
151-
parcel-css: 4.602ms
152-
143154 bytes
151+
parcel-css: 4.345ms
152+
143121 bytes
153153
154154
155155
$ node bench.js animate.css

node/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ serde_bytes = "0.11.5"
1414
serde_json = "*"
1515
cssparser = "0.29.1"
1616
parcel_css = { path = "../" }
17-
parcel_sourcemap = "2.0.0"
17+
parcel_sourcemap = "2.0.2"
1818

1919
[target.'cfg(target_os = "macos")'.dependencies]
2020
jemallocator = { version = "0.3.2", features = ["disable_initial_exec_tls"] }

node/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl<'i> From<parcel_sourcemap::SourceMapError> for CompileError<'i> {
333333
impl<'i> From<CompileError<'i>> for napi::Error {
334334
fn from(e: CompileError) -> napi::Error {
335335
match e {
336-
CompileError::SourceMapError(e) => e.into(),
336+
CompileError::SourceMapError(e) => napi::Error::from_reason(e.to_string()),
337337
_ => napi::Error::new(napi::Status::GenericFailure, e.reason())
338338
}
339339
}

selectors/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ fxhash = "0.2"
2525
log = "0.4"
2626
phf = "0.8"
2727
precomputed-hash = "0.1"
28-
servo_arc = "0.1"
2928
smallvec = "1.0"
3029

3130
[build-dependencies]

selectors/attr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ use cssparser::ToCss;
77
use std::fmt;
88

99
#[derive(Clone, Eq, PartialEq)]
10-
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
10+
pub struct AttrSelectorWithOptionalNamespace<'i, Impl: SelectorImpl<'i>> {
1111
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
1212
pub local_name: Impl::LocalName,
1313
pub local_name_lower: Impl::LocalName,
1414
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
1515
pub never_matches: bool,
1616
}
1717

18-
impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
18+
impl<'i, Impl: SelectorImpl<'i>> AttrSelectorWithOptionalNamespace<'i, Impl> {
1919
pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUrl>> {
2020
self.namespace.as_ref().map(|ns| match ns {
2121
NamespaceConstraint::Any => NamespaceConstraint::Any,

selectors/builder.rs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
2020
use crate::parser::{Combinator, Component, SelectorImpl};
2121
use crate::sink::Push;
22-
use servo_arc::{Arc, HeaderWithLength, ThinArc};
22+
// use servo_arc::{Arc, HeaderWithLength, ThinArc};
2323
use smallvec::{self, SmallVec};
2424
use std::cmp;
2525
use std::iter;
@@ -36,21 +36,21 @@ use std::slice;
3636
/// build(), which transforms the contents of the SelectorBuilder into a heap-
3737
/// allocated Selector and leaves the builder in a drained state.
3838
#[derive(Debug)]
39-
pub struct SelectorBuilder<Impl: SelectorImpl> {
39+
pub struct SelectorBuilder<'i, Impl: SelectorImpl<'i>> {
4040
/// The entire sequence of simple selectors, from left to right, without combinators.
4141
///
4242
/// We make this large because the result of parsing a selector is fed into a new
4343
/// Arc-ed allocation, so any spilled vec would be a wasted allocation. Also,
4444
/// Components are large enough that we don't have much cache locality benefit
4545
/// from reserving stack space for fewer of them.
46-
simple_selectors: SmallVec<[Component<Impl>; 32]>,
46+
simple_selectors: SmallVec<[Component<'i, Impl>; 32]>,
4747
/// The combinators, and the length of the compound selector to their left.
4848
combinators: SmallVec<[(Combinator, usize); 16]>,
4949
/// The length of the current compount selector.
5050
current_len: usize,
5151
}
5252

53-
impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
53+
impl<'i, Impl: SelectorImpl<'i>> Default for SelectorBuilder<'i, Impl> {
5454
#[inline(always)]
5555
fn default() -> Self {
5656
SelectorBuilder {
@@ -61,16 +61,16 @@ impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
6161
}
6262
}
6363

64-
impl<Impl: SelectorImpl> Push<Component<Impl>> for SelectorBuilder<Impl> {
65-
fn push(&mut self, value: Component<Impl>) {
64+
impl<'i, Impl: SelectorImpl<'i>> Push<Component<'i, Impl>> for SelectorBuilder<'i, Impl> {
65+
fn push(&mut self, value: Component<'i, Impl>) {
6666
self.push_simple_selector(value);
6767
}
6868
}
6969

70-
impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
70+
impl<'i, Impl: SelectorImpl<'i>> SelectorBuilder<'i, Impl> {
7171
/// Pushes a simple selector onto the current compound selector.
7272
#[inline(always)]
73-
pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
73+
pub fn push_simple_selector(&mut self, ss: Component<'i, Impl>) {
7474
assert!(!ss.is_combinator());
7575
self.simple_selectors.push(ss);
7676
self.current_len += 1;
@@ -97,7 +97,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
9797
parsed_pseudo: bool,
9898
parsed_slotted: bool,
9999
parsed_part: bool,
100-
) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
100+
) -> (SpecificityAndFlags, Vec<Component<'i, Impl>>) {
101101
// Compute the specificity and flags.
102102
let specificity = specificity(self.simple_selectors.iter());
103103
let mut flags = SelectorFlags::empty();
@@ -119,16 +119,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
119119
pub fn build_with_specificity_and_flags(
120120
&mut self,
121121
spec: SpecificityAndFlags,
122-
) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
123-
// First, compute the total number of Components we'll need to allocate
124-
// space for.
125-
let full_len = self.simple_selectors.len() + self.combinators.len();
126-
127-
// Create the header.
128-
let header = HeaderWithLength::new(spec, full_len);
129-
130-
// Create the Arc using an iterator that drains our buffers.
131-
122+
) -> (SpecificityAndFlags, Vec<Component<'i, Impl>>) {
132123
// Use a raw pointer to be able to call set_len despite "borrowing" the slice.
133124
// This is similar to SmallVec::drain, but we use a slice here because
134125
// we’re gonna traverse it non-linearly.
@@ -145,26 +136,26 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
145136
combinators: self.combinators.drain(..).rev(),
146137
};
147138

148-
Arc::into_thin(Arc::from_header_and_iter(header, iter))
139+
(spec, iter.collect())
149140
}
150141
}
151142

152-
struct SelectorBuilderIter<'a, Impl: SelectorImpl> {
153-
current_simple_selectors: slice::Iter<'a, Component<Impl>>,
154-
rest_of_simple_selectors: &'a [Component<Impl>],
143+
struct SelectorBuilderIter<'a, 'i, Impl: SelectorImpl<'i>> {
144+
current_simple_selectors: slice::Iter<'a, Component<'i, Impl>>,
145+
rest_of_simple_selectors: &'a [Component<'i, Impl>],
155146
combinators: iter::Rev<smallvec::Drain<'a, [(Combinator, usize); 16]>>,
156147
}
157148

158-
impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> {
149+
impl<'a, 'i, Impl: SelectorImpl<'i>> ExactSizeIterator for SelectorBuilderIter<'a, 'i, Impl> {
159150
fn len(&self) -> usize {
160151
self.current_simple_selectors.len() +
161152
self.rest_of_simple_selectors.len() +
162153
self.combinators.len()
163154
}
164155
}
165156

166-
impl<'a, Impl: SelectorImpl> Iterator for SelectorBuilderIter<'a, Impl> {
167-
type Item = Component<Impl>;
157+
impl<'a, 'i, Impl: SelectorImpl<'i>> Iterator for SelectorBuilderIter<'a, 'i, Impl> {
158+
type Item = Component<'i, Impl>;
168159
#[inline(always)]
169160
fn next(&mut self) -> Option<Self::Item> {
170161
if let Some(simple_selector_ref) = self.current_simple_selectors.next() {
@@ -262,22 +253,22 @@ impl From<Specificity> for u32 {
262253
}
263254
}
264255

265-
fn specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> u32
256+
fn specificity<'i, Impl>(iter: slice::Iter<Component<'i, Impl>>) -> u32
266257
where
267-
Impl: SelectorImpl,
258+
Impl: SelectorImpl<'i>,
268259
{
269260
complex_selector_specificity(iter).into()
270261
}
271262

272-
fn complex_selector_specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> Specificity
263+
fn complex_selector_specificity<'i, Impl>(iter: slice::Iter<Component<'i, Impl>>) -> Specificity
273264
where
274-
Impl: SelectorImpl,
265+
Impl: SelectorImpl<'i>,
275266
{
276-
fn simple_selector_specificity<Impl>(
277-
simple_selector: &Component<Impl>,
267+
fn simple_selector_specificity<'i, Impl>(
268+
simple_selector: &Component<'i, Impl>,
278269
specificity: &mut Specificity,
279270
) where
280-
Impl: SelectorImpl,
271+
Impl: SelectorImpl<'i>,
281272
{
282273
match *simple_selector {
283274
Component::Combinator(..) => {

selectors/context.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ impl QuirksMode {
9494
/// Data associated with the matching process for a element. This context is
9595
/// used across many selectors for an element, so it's not appropriate for
9696
/// transient data that applies to only a single selector.
97-
pub struct MatchingContext<'a, Impl>
97+
pub struct MatchingContext<'a, 'i, Impl>
9898
where
99-
Impl: SelectorImpl,
99+
Impl: SelectorImpl<'i>,
100100
{
101101
/// Input with the matching mode we should use when matching selectors.
102102
matching_mode: MatchingMode,
@@ -144,9 +144,9 @@ where
144144
_impl: ::std::marker::PhantomData<Impl>,
145145
}
146146

147-
impl<'a, Impl> MatchingContext<'a, Impl>
147+
impl<'a, 'i, Impl> MatchingContext<'a, 'i, Impl>
148148
where
149-
Impl: SelectorImpl,
149+
Impl: SelectorImpl<'i>,
150150
{
151151
/// Constructs a new `MatchingContext`.
152152
pub fn new(
@@ -272,7 +272,7 @@ where
272272
#[inline]
273273
pub fn with_shadow_host<F, E, R>(&mut self, host: Option<E>, f: F) -> R
274274
where
275-
E: Element,
275+
E: Element<'i>,
276276
F: FnOnce(&mut Self) -> R,
277277
{
278278
let original_host = self.current_host.take();

selectors/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ extern crate fxhash;
1616
extern crate log;
1717
extern crate phf;
1818
extern crate precomputed_hash;
19-
extern crate servo_arc;
2019
extern crate smallvec;
2120

2221
pub mod attr;

0 commit comments

Comments
 (0)