mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Shrink selectors::Component to 24 bytes.
This saves about 37 KiB of memory across the UA style sheets. Bug: 1475197 Reviewed-by: emilio
This commit is contained in:
parent
b05ace3e4a
commit
62419adaaa
12 changed files with 96 additions and 50 deletions
|
@ -37,6 +37,7 @@ servo_arc = { path = "../servo_arc" }
|
||||||
smallbitvec = "2.1.0"
|
smallbitvec = "2.1.0"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
string_cache = { version = "0.7", optional = true }
|
string_cache = { version = "0.7", optional = true }
|
||||||
|
thin-slice = "0.1.0"
|
||||||
time = { version = "0.1.17", optional = true }
|
time = { version = "0.1.17", optional = true }
|
||||||
url = { version = "1.2", optional = true }
|
url = { version = "1.2", optional = true }
|
||||||
webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
|
webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
|
||||||
|
|
|
@ -63,6 +63,7 @@ extern crate smallbitvec;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
extern crate string_cache;
|
extern crate string_cache;
|
||||||
|
extern crate thin_slice;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
extern crate time;
|
extern crate time;
|
||||||
#[cfg(feature = "url")]
|
#[cfg(feature = "url")]
|
||||||
|
@ -231,6 +232,24 @@ impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> MallocShallowSizeOf for thin_slice::ThinBoxedSlice<T> {
|
||||||
|
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
|
let mut n = 0;
|
||||||
|
unsafe {
|
||||||
|
n += thin_slice::ThinBoxedSlice::spilled_storage(self)
|
||||||
|
.map_or(0, |ptr| ops.malloc_size_of(ptr));
|
||||||
|
n += ops.malloc_size_of(&**self);
|
||||||
|
}
|
||||||
|
n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MallocSizeOf> MallocSizeOf for thin_slice::ThinBoxedSlice<T> {
|
||||||
|
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
|
self.shallow_size_of(ops) + (**self).size_of(ops)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MallocSizeOf for () {
|
impl MallocSizeOf for () {
|
||||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||||
0
|
0
|
||||||
|
@ -770,7 +789,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
|
impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
|
||||||
for selectors::attr::AttrSelectorWithNamespace<Impl>
|
for selectors::attr::AttrSelectorWithOptionalNamespace<Impl>
|
||||||
{
|
{
|
||||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||||
0
|
0
|
||||||
|
|
|
@ -30,6 +30,7 @@ phf = "0.7.18"
|
||||||
precomputed-hash = "0.1"
|
precomputed-hash = "0.1"
|
||||||
servo_arc = { version = "0.1", path = "../servo_arc" }
|
servo_arc = { version = "0.1", path = "../servo_arc" }
|
||||||
smallvec = "0.6.2"
|
smallvec = "0.6.2"
|
||||||
|
thin-slice = "0.1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
phf_codegen = "0.7.18"
|
phf_codegen = "0.7.18"
|
||||||
|
|
|
@ -7,20 +7,20 @@ use parser::SelectorImpl;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct AttrSelectorWithNamespace<Impl: SelectorImpl> {
|
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
|
||||||
pub namespace: NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>,
|
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
|
||||||
pub local_name: Impl::LocalName,
|
pub local_name: Impl::LocalName,
|
||||||
pub local_name_lower: Impl::LocalName,
|
pub local_name_lower: Impl::LocalName,
|
||||||
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
|
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
|
||||||
pub never_matches: bool,
|
pub never_matches: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> AttrSelectorWithNamespace<Impl> {
|
impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
|
||||||
pub fn namespace(&self) -> NamespaceConstraint<&Impl::NamespaceUrl> {
|
pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUrl>> {
|
||||||
match self.namespace {
|
self.namespace.as_ref().map(|ns| match ns {
|
||||||
NamespaceConstraint::Any => NamespaceConstraint::Any,
|
NamespaceConstraint::Any => NamespaceConstraint::Any,
|
||||||
NamespaceConstraint::Specific((_, ref url)) => NamespaceConstraint::Specific(url),
|
NamespaceConstraint::Specific((_, ref url)) => NamespaceConstraint::Specific(url),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ extern crate phf;
|
||||||
extern crate precomputed_hash;
|
extern crate precomputed_hash;
|
||||||
extern crate servo_arc;
|
extern crate servo_arc;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
|
extern crate thin_slice;
|
||||||
|
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
pub mod bloom;
|
pub mod bloom;
|
||||||
|
|
|
@ -699,7 +699,6 @@ where
|
||||||
},
|
},
|
||||||
Component::AttributeInNoNamespace {
|
Component::AttributeInNoNamespace {
|
||||||
ref local_name,
|
ref local_name,
|
||||||
ref local_name_lower,
|
|
||||||
ref value,
|
ref value,
|
||||||
operator,
|
operator,
|
||||||
case_sensitivity,
|
case_sensitivity,
|
||||||
|
@ -711,7 +710,7 @@ where
|
||||||
let is_html = element.is_html_element_in_html_document();
|
let is_html = element.is_html_element_in_html_document();
|
||||||
element.attr_matches(
|
element.attr_matches(
|
||||||
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
||||||
select_name(is_html, local_name, local_name_lower),
|
local_name,
|
||||||
&AttrSelectorOperation::WithValue {
|
&AttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity.to_unconditional(is_html),
|
case_sensitivity: case_sensitivity.to_unconditional(is_html),
|
||||||
|
@ -724,8 +723,16 @@ where
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let is_html = element.is_html_element_in_html_document();
|
let is_html = element.is_html_element_in_html_document();
|
||||||
|
let empty_string;
|
||||||
|
let namespace = match attr_sel.namespace() {
|
||||||
|
Some(ns) => ns,
|
||||||
|
None => {
|
||||||
|
empty_string = ::parser::namespace_empty_string::<E::Impl>();
|
||||||
|
NamespaceConstraint::Specific(&empty_string)
|
||||||
|
}
|
||||||
|
};
|
||||||
element.attr_matches(
|
element.attr_matches(
|
||||||
&attr_sel.namespace(),
|
&namespace,
|
||||||
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
||||||
&match attr_sel.operation {
|
&match attr_sel.operation {
|
||||||
ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use attr::{AttrSelectorOperator, AttrSelectorWithNamespace, ParsedAttrSelectorOperation};
|
use attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace};
|
||||||
use attr::{NamespaceConstraint, ParsedCaseSensitivity, SELECTOR_WHITESPACE};
|
use attr::{NamespaceConstraint, ParsedAttrSelectorOperation};
|
||||||
|
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE};
|
||||||
use bloom::BLOOM_HASH_MASK;
|
use bloom::BLOOM_HASH_MASK;
|
||||||
use builder::{SelectorBuilder, SpecificityAndFlags};
|
use builder::{SelectorBuilder, SpecificityAndFlags};
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
|
@ -19,6 +20,7 @@ use std::borrow::{Borrow, Cow};
|
||||||
use std::fmt::{self, Debug, Display, Write};
|
use std::fmt::{self, Debug, Display, Write};
|
||||||
use std::iter::Rev;
|
use std::iter::Rev;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
use thin_slice::ThinBoxedSlice;
|
||||||
pub use visitor::{SelectorVisitor, Visit};
|
pub use visitor::{SelectorVisitor, Visit};
|
||||||
|
|
||||||
/// A trait that represents a pseudo-element.
|
/// A trait that represents a pseudo-element.
|
||||||
|
@ -45,6 +47,8 @@ pub trait NonTSPseudoClass: Sized + ToCss {
|
||||||
fn is_active_or_hover(&self) -> bool;
|
fn is_active_or_hover(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
|
||||||
|
/// Cow::Owned if `s` had to be converted into ASCII lowercase.
|
||||||
fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
||||||
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
|
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
|
||||||
let mut string = s.to_owned();
|
let mut string = s.to_owned();
|
||||||
|
@ -428,7 +432,6 @@ where
|
||||||
},
|
},
|
||||||
AttributeInNoNamespace {
|
AttributeInNoNamespace {
|
||||||
ref local_name,
|
ref local_name,
|
||||||
ref local_name_lower,
|
|
||||||
never_matches,
|
never_matches,
|
||||||
..
|
..
|
||||||
} if !never_matches =>
|
} if !never_matches =>
|
||||||
|
@ -436,14 +439,22 @@ where
|
||||||
if !visitor.visit_attribute_selector(
|
if !visitor.visit_attribute_selector(
|
||||||
&NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
|
&NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
|
||||||
local_name,
|
local_name,
|
||||||
local_name_lower,
|
local_name,
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AttributeOther(ref attr_selector) if !attr_selector.never_matches => {
|
AttributeOther(ref attr_selector) if !attr_selector.never_matches => {
|
||||||
|
let empty_string;
|
||||||
|
let namespace = match attr_selector.namespace() {
|
||||||
|
Some(ns) => ns,
|
||||||
|
None => {
|
||||||
|
empty_string = ::parser::namespace_empty_string::<Impl>();
|
||||||
|
NamespaceConstraint::Specific(&empty_string)
|
||||||
|
}
|
||||||
|
};
|
||||||
if !visitor.visit_attribute_selector(
|
if !visitor.visit_attribute_selector(
|
||||||
&attr_selector.namespace(),
|
&namespace,
|
||||||
&attr_selector.local_name,
|
&attr_selector.local_name,
|
||||||
&attr_selector.local_name_lower,
|
&attr_selector.local_name_lower,
|
||||||
) {
|
) {
|
||||||
|
@ -815,16 +826,16 @@ pub enum Component<Impl: SelectorImpl> {
|
||||||
local_name: Impl::LocalName,
|
local_name: Impl::LocalName,
|
||||||
local_name_lower: Impl::LocalName,
|
local_name_lower: Impl::LocalName,
|
||||||
},
|
},
|
||||||
|
// Used only when local_name is already lowercase.
|
||||||
AttributeInNoNamespace {
|
AttributeInNoNamespace {
|
||||||
local_name: Impl::LocalName,
|
local_name: Impl::LocalName,
|
||||||
local_name_lower: Impl::LocalName,
|
|
||||||
operator: AttrSelectorOperator,
|
operator: AttrSelectorOperator,
|
||||||
value: Impl::AttrValue,
|
value: Impl::AttrValue,
|
||||||
case_sensitivity: ParsedCaseSensitivity,
|
case_sensitivity: ParsedCaseSensitivity,
|
||||||
never_matches: bool,
|
never_matches: bool,
|
||||||
},
|
},
|
||||||
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
||||||
AttributeOther(Box<AttrSelectorWithNamespace<Impl>>),
|
AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
|
||||||
|
|
||||||
/// Pseudo-classes
|
/// Pseudo-classes
|
||||||
///
|
///
|
||||||
|
@ -836,7 +847,7 @@ pub enum Component<Impl: SelectorImpl> {
|
||||||
/// need to think about how this should interact with
|
/// need to think about how this should interact with
|
||||||
/// visit_complex_selector, and what the consumers of those APIs should do
|
/// visit_complex_selector, and what the consumers of those APIs should do
|
||||||
/// about the presence of combinators in negation.
|
/// about the presence of combinators in negation.
|
||||||
Negation(Box<[Component<Impl>]>),
|
Negation(ThinBoxedSlice<Component<Impl>>),
|
||||||
FirstChild,
|
FirstChild,
|
||||||
LastChild,
|
LastChild,
|
||||||
OnlyChild,
|
OnlyChild,
|
||||||
|
@ -948,7 +959,7 @@ impl<Impl: SelectorImpl> Debug for Component<Impl> {
|
||||||
self.to_css(f)
|
self.to_css(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Impl: SelectorImpl> Debug for AttrSelectorWithNamespace<Impl> {
|
impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
self.to_css(f)
|
self.to_css(f)
|
||||||
}
|
}
|
||||||
|
@ -1238,18 +1249,19 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> ToCss for AttrSelectorWithNamespace<Impl> {
|
impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: fmt::Write,
|
W: fmt::Write,
|
||||||
{
|
{
|
||||||
dest.write_char('[')?;
|
dest.write_char('[')?;
|
||||||
match self.namespace {
|
match self.namespace {
|
||||||
NamespaceConstraint::Specific((ref prefix, _)) => {
|
Some(NamespaceConstraint::Specific((ref prefix, _))) => {
|
||||||
display_to_css_identifier(prefix, dest)?;
|
display_to_css_identifier(prefix, dest)?;
|
||||||
dest.write_char('|')?
|
dest.write_char('|')?
|
||||||
},
|
},
|
||||||
NamespaceConstraint::Any => dest.write_str("*|")?,
|
Some(NamespaceConstraint::Any) => dest.write_str("*|")?,
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
display_to_css_identifier(&self.local_name, dest)?;
|
display_to_css_identifier(&self.local_name, dest)?;
|
||||||
match self.operation {
|
match self.operation {
|
||||||
|
@ -1628,8 +1640,8 @@ where
|
||||||
let local_name = local_name.as_ref().into();
|
let local_name = local_name.as_ref().into();
|
||||||
if let Some(namespace) = namespace {
|
if let Some(namespace) = namespace {
|
||||||
return Ok(Component::AttributeOther(Box::new(
|
return Ok(Component::AttributeOther(Box::new(
|
||||||
AttrSelectorWithNamespace {
|
AttrSelectorWithOptionalNamespace {
|
||||||
namespace: namespace,
|
namespace: Some(namespace),
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
local_name_lower: local_name_lower,
|
local_name_lower: local_name_lower,
|
||||||
operation: ParsedAttrSelectorOperation::Exists,
|
operation: ParsedAttrSelectorOperation::Exists,
|
||||||
|
@ -1685,6 +1697,7 @@ where
|
||||||
|
|
||||||
let value = value.as_ref().into();
|
let value = value.as_ref().into();
|
||||||
let local_name_lower;
|
let local_name_lower;
|
||||||
|
let local_name_is_ascii_lowercase;
|
||||||
{
|
{
|
||||||
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
||||||
if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
|
if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
|
||||||
|
@ -1699,15 +1712,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name_lower = local_name_lower_cow.as_ref().into();
|
local_name_lower = local_name_lower_cow.as_ref().into();
|
||||||
|
local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
|
||||||
}
|
}
|
||||||
let local_name = local_name.as_ref().into();
|
let local_name = local_name.as_ref().into();
|
||||||
if let Some(namespace) = namespace {
|
if namespace.is_some() || !local_name_is_ascii_lowercase {
|
||||||
Ok(Component::AttributeOther(Box::new(
|
Ok(Component::AttributeOther(Box::new(
|
||||||
AttrSelectorWithNamespace {
|
AttrSelectorWithOptionalNamespace {
|
||||||
namespace: namespace,
|
namespace,
|
||||||
local_name: local_name,
|
local_name,
|
||||||
local_name_lower: local_name_lower,
|
local_name_lower,
|
||||||
never_matches: never_matches,
|
never_matches,
|
||||||
operation: ParsedAttrSelectorOperation::WithValue {
|
operation: ParsedAttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity,
|
case_sensitivity: case_sensitivity,
|
||||||
|
@ -1718,7 +1732,6 @@ where
|
||||||
} else {
|
} else {
|
||||||
Ok(Component::AttributeInNoNamespace {
|
Ok(Component::AttributeInNoNamespace {
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
local_name_lower: local_name_lower,
|
|
||||||
operator: operator,
|
operator: operator,
|
||||||
value: value,
|
value: value,
|
||||||
case_sensitivity: case_sensitivity,
|
case_sensitivity: case_sensitivity,
|
||||||
|
@ -1785,7 +1798,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success.
|
// Success.
|
||||||
Ok(Component::Negation(sequence.into_vec().into_boxed_slice()))
|
Ok(Component::Negation(sequence.into_vec().into_boxed_slice().into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// simple_selector_sequence
|
/// simple_selector_sequence
|
||||||
|
@ -2625,7 +2638,7 @@ pub mod tests {
|
||||||
vec![
|
vec![
|
||||||
Component::DefaultNamespace(MATHML.into()),
|
Component::DefaultNamespace(MATHML.into()),
|
||||||
Component::Negation(
|
Component::Negation(
|
||||||
vec![Component::Class(DummyAtom::from("cl"))].into_boxed_slice(),
|
vec![Component::Class(DummyAtom::from("cl"))].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 1, 0),
|
specificity(0, 1, 0),
|
||||||
|
@ -2642,7 +2655,7 @@ pub mod tests {
|
||||||
vec![
|
vec![
|
||||||
Component::DefaultNamespace(MATHML.into()),
|
Component::DefaultNamespace(MATHML.into()),
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
].into_boxed_slice(),
|
].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
|
@ -2662,7 +2675,7 @@ pub mod tests {
|
||||||
name: DummyAtom::from("e"),
|
name: DummyAtom::from("e"),
|
||||||
lower_name: DummyAtom::from("e"),
|
lower_name: DummyAtom::from("e"),
|
||||||
}),
|
}),
|
||||||
].into_boxed_slice(),
|
].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 1),
|
specificity(0, 0, 1),
|
||||||
|
@ -2676,7 +2689,6 @@ pub mod tests {
|
||||||
vec![
|
vec![
|
||||||
Component::AttributeInNoNamespace {
|
Component::AttributeInNoNamespace {
|
||||||
local_name: DummyAtom::from("attr"),
|
local_name: DummyAtom::from("attr"),
|
||||||
local_name_lower: DummyAtom::from("attr"),
|
|
||||||
operator: AttrSelectorOperator::DashMatch,
|
operator: AttrSelectorOperator::DashMatch,
|
||||||
value: DummyAtom::from("foo"),
|
value: DummyAtom::from("foo"),
|
||||||
never_matches: false,
|
never_matches: false,
|
||||||
|
@ -2770,7 +2782,7 @@ pub mod tests {
|
||||||
Selector::from_vec(
|
Selector::from_vec(
|
||||||
vec![
|
vec![
|
||||||
Component::Negation(
|
Component::Negation(
|
||||||
vec![Component::ID(DummyAtom::from("provel"))].into_boxed_slice(),
|
vec![Component::ID(DummyAtom::from("provel"))].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(1, 0, 0),
|
specificity(1, 0, 0),
|
||||||
|
@ -2789,7 +2801,7 @@ pub mod tests {
|
||||||
name: DummyAtom::from("circle"),
|
name: DummyAtom::from("circle"),
|
||||||
lower_name: DummyAtom::from("circle"),
|
lower_name: DummyAtom::from("circle"),
|
||||||
}),
|
}),
|
||||||
].into_boxed_slice(),
|
].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 1),
|
specificity(0, 0, 1),
|
||||||
|
@ -2803,7 +2815,7 @@ pub mod tests {
|
||||||
Selector::from_vec(
|
Selector::from_vec(
|
||||||
vec![
|
vec![
|
||||||
Component::Negation(
|
Component::Negation(
|
||||||
vec![Component::ExplicitUniversalType].into_boxed_slice(),
|
vec![Component::ExplicitUniversalType].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
|
@ -2819,7 +2831,7 @@ pub mod tests {
|
||||||
vec![
|
vec![
|
||||||
Component::ExplicitNoNamespace,
|
Component::ExplicitNoNamespace,
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
].into_boxed_slice(),
|
].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
|
@ -2834,7 +2846,7 @@ pub mod tests {
|
||||||
Selector::from_vec(
|
Selector::from_vec(
|
||||||
vec![
|
vec![
|
||||||
Component::Negation(
|
Component::Negation(
|
||||||
vec![Component::ExplicitUniversalType].into_boxed_slice(),
|
vec![Component::ExplicitUniversalType].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
|
@ -2850,7 +2862,7 @@ pub mod tests {
|
||||||
vec![
|
vec![
|
||||||
Component::Namespace(DummyAtom("svg".into()), SVG.into()),
|
Component::Namespace(DummyAtom("svg".into()), SVG.into()),
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
].into_boxed_slice(),
|
].into_boxed_slice().into(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
|
|
|
@ -65,6 +65,7 @@ string_cache = { version = "0.7", optional = true }
|
||||||
style_derive = {path = "../style_derive"}
|
style_derive = {path = "../style_derive"}
|
||||||
style_traits = {path = "../style_traits"}
|
style_traits = {path = "../style_traits"}
|
||||||
servo_url = {path = "../url", optional = true}
|
servo_url = {path = "../url", optional = true}
|
||||||
|
thin-slice = "0.1.0"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
uluru = "0.2"
|
uluru = "0.2"
|
||||||
unicode-bidi = "0.3"
|
unicode-bidi = "0.3"
|
||||||
|
|
|
@ -15,6 +15,7 @@ use properties::longhands::display::computed_value::T as Display;
|
||||||
use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl};
|
use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
|
use thin_slice::ThinBoxedSlice;
|
||||||
use values::serialize_atom_identifier;
|
use values::serialize_atom_identifier;
|
||||||
|
|
||||||
include!(concat!(
|
include!(concat!(
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub enum PseudoElement {
|
||||||
% for pseudo in PSEUDOS:
|
% for pseudo in PSEUDOS:
|
||||||
/// ${pseudo.value}
|
/// ${pseudo.value}
|
||||||
% if pseudo.is_tree_pseudo_element():
|
% if pseudo.is_tree_pseudo_element():
|
||||||
${pseudo.capitalized()}(Box<[Atom]>),
|
${pseudo.capitalized()}(ThinBoxedSlice<Atom>),
|
||||||
% else:
|
% else:
|
||||||
${pseudo.capitalized()},
|
${pseudo.capitalized()},
|
||||||
% endif
|
% endif
|
||||||
|
@ -209,7 +209,7 @@ impl PseudoElement {
|
||||||
% for pseudo in PSEUDOS:
|
% for pseudo in PSEUDOS:
|
||||||
% if pseudo.is_tree_pseudo_element():
|
% if pseudo.is_tree_pseudo_element():
|
||||||
if atom == &atom!("${pseudo.value}") {
|
if atom == &atom!("${pseudo.value}") {
|
||||||
return Some(PseudoElement::${pseudo.capitalized()}(args));
|
return Some(PseudoElement::${pseudo.capitalized()}(args.into()));
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -256,7 +256,7 @@ impl PseudoElement {
|
||||||
let tree_part = &name[10..];
|
let tree_part = &name[10..];
|
||||||
% for pseudo in TREE_PSEUDOS:
|
% for pseudo in TREE_PSEUDOS:
|
||||||
if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") {
|
if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") {
|
||||||
return Some(${pseudo_element_variant(pseudo, "args")});
|
return Some(${pseudo_element_variant(pseudo, "args.into()")});
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
None
|
None
|
||||||
|
|
|
@ -13,11 +13,13 @@ use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use invalidation::element::document_state::InvalidationMatchingData;
|
use invalidation::element::document_state::InvalidationMatchingData;
|
||||||
use selector_parser::{Direction, SelectorParser};
|
use selector_parser::{Direction, SelectorParser};
|
||||||
use selectors::SelectorList;
|
use selectors::SelectorList;
|
||||||
use selectors::parser::{self as selector_parser, Selector, SelectorParseErrorKind, Visit};
|
use selectors::parser::{self as selector_parser, Selector};
|
||||||
|
use selectors::parser::{SelectorParseErrorKind, Visit};
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_};
|
||||||
|
use thin_slice::ThinBoxedSlice;
|
||||||
|
|
||||||
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT, PSEUDO_COUNT};
|
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT, PSEUDO_COUNT};
|
||||||
pub use gecko::snapshot::SnapshotMap;
|
pub use gecko::snapshot::SnapshotMap;
|
||||||
|
@ -34,7 +36,7 @@ bitflags! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type used for storing pseudo-class string arguments.
|
/// The type used for storing pseudo-class string arguments.
|
||||||
pub type PseudoClassStringArg = Box<[u16]>;
|
pub type PseudoClassStringArg = ThinBoxedSlice<u16>;
|
||||||
|
|
||||||
macro_rules! pseudo_class_name {
|
macro_rules! pseudo_class_name {
|
||||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||||
|
@ -56,7 +58,7 @@ macro_rules! pseudo_class_name {
|
||||||
///
|
///
|
||||||
/// TODO(emilio): We disallow combinators and pseudos here, so we
|
/// TODO(emilio): We disallow combinators and pseudos here, so we
|
||||||
/// should use SimpleSelector instead
|
/// should use SimpleSelector instead
|
||||||
MozAny(Box<[Selector<SelectorImpl>]>),
|
MozAny(ThinBoxedSlice<Selector<SelectorImpl>>),
|
||||||
/// The non-standard `:-moz-locale-dir` pseudo-class.
|
/// The non-standard `:-moz-locale-dir` pseudo-class.
|
||||||
MozLocaleDir(Box<Direction>),
|
MozLocaleDir(Box<Direction>),
|
||||||
}
|
}
|
||||||
|
@ -405,7 +407,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
// convert to null terminated utf16 string
|
// convert to null terminated utf16 string
|
||||||
// since that's what Gecko deals with
|
// since that's what Gecko deals with
|
||||||
let utf16: Vec<u16> = name.encode_utf16().chain(Some(0u16)).collect();
|
let utf16: Vec<u16> = name.encode_utf16().chain(Some(0u16)).collect();
|
||||||
NonTSPseudoClass::$s_name(utf16.into_boxed_slice())
|
NonTSPseudoClass::$s_name(utf16.into_boxed_slice().into())
|
||||||
}, )*
|
}, )*
|
||||||
"-moz-locale-dir" => {
|
"-moz-locale-dir" => {
|
||||||
NonTSPseudoClass::MozLocaleDir(
|
NonTSPseudoClass::MozLocaleDir(
|
||||||
|
@ -422,7 +424,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
selector_parser::parse_compound_selector_list(
|
selector_parser::parse_compound_selector_list(
|
||||||
self,
|
self,
|
||||||
parser,
|
parser,
|
||||||
)?
|
)?.into()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => return Err(parser.new_custom_error(
|
_ => return Err(parser.new_custom_error(
|
||||||
|
|
|
@ -93,6 +93,7 @@ extern crate string_cache;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate style_derive;
|
extern crate style_derive;
|
||||||
extern crate style_traits;
|
extern crate style_traits;
|
||||||
|
extern crate thin_slice;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate uluru;
|
extern crate uluru;
|
||||||
extern crate unicode_bidi;
|
extern crate unicode_bidi;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue