Add string_cache override for geckolib based on gecko atoms.

The work in these patches is based on Ms2ger's gecko-atom crate.
This commit is contained in:
Bobby Holley 2016-05-11 11:43:54 -07:00
parent 825f610dec
commit b521c293dc
25 changed files with 5153 additions and 185 deletions

View file

@ -28,7 +28,7 @@ matches = "0.1"
num-traits = "0.1.32"
plugins = {path = "../plugins"}
rustc-serialize = "0.3"
selectors = {version = "0.5", features = ["heap_size", "unstable"]}
selectors = {version = "0.6", features = ["heap_size", "unstable"]}
serde = {version = "0.7", features = ["nightly"]}
serde_macros = "0.7"
smallvec = "0.1"

View file

@ -7,12 +7,11 @@ use cssparser::{self, Color, RGBA};
use euclid::num::Zero;
use num_traits::ToPrimitive;
use std::ascii::AsciiExt;
use std::ops::Deref;
use std::str::FromStr;
use string_cache::{Atom, Namespace};
use url::Url;
use util::str::{DOMString, LengthOrPercentageOrAuto, HTML_SPACE_CHARACTERS};
use util::str::{read_exponent, read_fraction, read_numbers, split_html_space_chars, str_join};
use util::str::{read_exponent, read_fraction, read_numbers, split_html_space_chars};
use values::specified::{Length};
// Duplicated from script::dom::values.
@ -125,7 +124,9 @@ impl AttrValue {
AttrValue::TokenList(tokens, atoms)
}
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
use util::str::str_join;
// TODO(ajeffrey): effecient conversion of Vec<Atom> to DOMString
let tokens = DOMString::from(str_join(&atoms, "\x20"));
AttrValue::TokenList(tokens, atoms)
@ -293,7 +294,8 @@ impl AttrValue {
}
}
impl Deref for AttrValue {
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
impl ::std::ops::Deref for AttrValue {
type Target = str;
fn deref(&self) -> &str {

View file

@ -616,8 +616,8 @@ pub trait MatchMethods : TNode {
fn insert_into_bloom_filter(&self, bf: &mut BloomFilter) {
// Only elements are interesting.
if let Some(element) = self.as_element() {
bf.insert(element.get_local_name());
bf.insert(element.get_namespace());
bf.insert(&*element.get_local_name());
bf.insert(&*element.get_namespace());
element.get_id().map(|id| bf.insert(&id));
// TODO: case-sensitivity depends on the document type and quirks mode
@ -630,8 +630,8 @@ pub trait MatchMethods : TNode {
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter) {
// Only elements are interesting.
if let Some(element) = self.as_element() {
bf.remove(element.get_local_name());
bf.remove(element.get_namespace());
bf.remove(&*element.get_local_name());
bf.remove(&*element.get_namespace());
element.get_id().map(|id| bf.remove(&id));
// TODO: case-sensitivity depends on the document type and quirks mode

View file

@ -13,12 +13,6 @@
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
const SERIF: &'static str = "serif";
const SANS_SERIF: &'static str = "sans-serif";
const CURSIVE: &'static str = "cursive";
const FANTASY: &'static str = "fantasy";
const MONOSPACE: &'static str = "monospace";
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value {
use cssparser::ToCss;
@ -28,45 +22,44 @@
#[derive(Debug, PartialEq, Eq, Clone, Hash, HeapSizeOf, Deserialize, Serialize)]
pub enum FontFamily {
FamilyName(Atom),
// Generic,
Serif,
SansSerif,
Cursive,
Fantasy,
Monospace,
Generic(Atom),
}
impl FontFamily {
#[inline]
pub fn name(&self) -> &str {
pub fn atom(&self) -> &Atom {
match *self {
FontFamily::FamilyName(ref name) => &*name,
FontFamily::Serif => super::SERIF,
FontFamily::SansSerif => super::SANS_SERIF,
FontFamily::Cursive => super::CURSIVE,
FontFamily::Fantasy => super::FANTASY,
FontFamily::Monospace => super::MONOSPACE
FontFamily::FamilyName(ref name) => name,
FontFamily::Generic(ref name) => name,
}
}
#[inline]
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
pub fn name(&self) -> &str {
self.atom()
}
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
pub fn from_atom(input: Atom) -> FontFamily {
let option = match_ignore_ascii_case! { &input,
super::SERIF => Some(FontFamily::Serif),
super::SANS_SERIF => Some(FontFamily::SansSerif),
super::CURSIVE => Some(FontFamily::Cursive),
super::FANTASY => Some(FontFamily::Fantasy),
super::MONOSPACE => Some(FontFamily::Monospace),
&atom!("serif") => Some(atom!("serif")),
&atom!("sans-serif") => Some(atom!("sans-serif")),
&atom!("cursive") => Some(atom!("cursive")),
&atom!("fantasy") => Some(atom!("fantasy")),
&atom!("monospace") => Some(atom!("monospace")),
_ => None
};
match option {
Some(family) => family,
Some(family) => FontFamily::Generic(family),
None => FontFamily::FamilyName(input)
}
}
}
impl ToCss for FontFamily {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_str(self.name())
self.atom().with_str(|s| dest.write_str(s))
}
}
impl ToCss for T {
@ -86,7 +79,7 @@
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(vec![FontFamily::Serif])
computed_value::T(vec![FontFamily::Generic(atom!("serif"))])
}
/// <family-name>#
/// <family-name> = <string> | [ <ident>+ ]
@ -100,14 +93,18 @@
}
let first_ident = try!(input.expect_ident());
match_ignore_ascii_case! { first_ident,
SERIF => return Ok(FontFamily::Serif),
SANS_SERIF => return Ok(FontFamily::SansSerif),
CURSIVE => return Ok(FontFamily::Cursive),
FANTASY => return Ok(FontFamily::Fantasy),
MONOSPACE => return Ok(FontFamily::Monospace),
// FIXME(bholley): The fast thing to do here would be to look up the
// string (as lowercase) in the static atoms table. We don't have an
// API to do that yet though, so we do the simple thing for now.
match &first_ident[..] {
s if atom!("serif").eq_str_ignore_ascii_case(s) => return Ok(FontFamily::Generic(atom!("serif"))),
s if atom!("sans-serif").eq_str_ignore_ascii_case(s) => return Ok(FontFamily::Generic(atom!("sans-serif"))),
s if atom!("cursive").eq_str_ignore_ascii_case(s) => return Ok(FontFamily::Generic(atom!("cursive"))),
s if atom!("fantasy").eq_str_ignore_ascii_case(s) => return Ok(FontFamily::Generic(atom!("fantasy"))),
s if atom!("monospace").eq_str_ignore_ascii_case(s) => return Ok(FontFamily::Generic(atom!("monospace"))),
_ => {}
}
let mut value = first_ident.into_owned();
while let Ok(ident) = input.try(|input| input.expect_ident()) {
value.push_str(" ");

View file

@ -478,7 +478,7 @@ impl PartialEq<str> for PropertyDeclarationName {
match *self {
PropertyDeclarationName::Longhand(n) => n == other,
PropertyDeclarationName::Custom(ref n) => {
::custom_properties::parse_name(other) == Ok(&**n)
n.with_str(|s| ::custom_properties::parse_name(other) == Ok(s))
}
PropertyDeclarationName::Internal => false,
}
@ -491,7 +491,7 @@ impl fmt::Display for PropertyDeclarationName {
PropertyDeclarationName::Longhand(n) => f.write_str(n),
PropertyDeclarationName::Custom(ref n) => {
try!(f.write_str("--"));
f.write_str(n)
n.with_str(|s| f.write_str(s))
}
PropertyDeclarationName::Internal => Ok(()),
}
@ -575,7 +575,7 @@ impl PropertyDeclaration {
% endif
% endfor
PropertyDeclaration::Custom(ref declaration_name, _) => {
::custom_properties::parse_name(name) == Ok(&**declaration_name)
declaration_name.with_str(|s| ::custom_properties::parse_name(name) == Ok(s))
}
}
}

View file

@ -7,10 +7,10 @@ use element_state::*;
use selector_impl::SelectorImplExt;
use selectors::Element;
use selectors::matching::matches_compound_selector;
use selectors::parser::{AttrSelector, Combinator, CompoundSelector, NamespaceConstraint, SelectorImpl, SimpleSelector};
use selectors::parser::{AttrSelector, Combinator, CompoundSelector, SelectorImpl, SimpleSelector};
use std::clone::Clone;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
/// When the ElementState of an element (like IN_HOVER_STATE) changes, certain
/// pseudo-classes (like :hover) may require us to restyle that element, its
@ -133,10 +133,10 @@ impl<'a, E> Element for ElementWrapper<'a, E>
fn is_html_element_in_html_document(&self) -> bool {
self.element.is_html_element_in_html_document()
}
fn get_local_name(&self) -> &Atom {
fn get_local_name(&self) -> BorrowedAtom {
self.element.get_local_name()
}
fn get_namespace(&self) -> &Namespace {
fn get_namespace(&self) -> BorrowedNamespace {
self.element.get_namespace()
}
fn get_id(&self) -> Option<Atom> {
@ -152,8 +152,15 @@ impl<'a, E> Element for ElementWrapper<'a, E>
None => self.element.has_class(name),
}
}
#[cfg(feature = "gecko")]
fn match_attr<F>(&self, _: &AttrSelector, _: F) -> bool
where F: Fn(&str) -> bool {
panic!("Gecko can't borrow atoms as UTF-8.");
}
#[cfg(not(feature = "gecko"))]
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
where F: Fn(&str) -> bool {
use selectors::parser::NamespaceConstraint;
match self.snapshot.attrs {
Some(_) => {
let html = self.is_html_element_in_html_document();