From fdb2071b2d146ddc07932d4c4a04f0c23ce77c03 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 15 Jul 2016 10:24:10 +0200 Subject: [PATCH] Update to selectors 0.8.2 --- components/layout/Cargo.toml | 2 +- components/layout/traversal.rs | 2 +- components/script/Cargo.toml | 2 +- components/script/dom/element.rs | 18 +- components/script/layout_wrapper.rs | 43 ++-- components/script_layout_interface/Cargo.toml | 2 +- .../script_layout_interface/wrapper_traits.rs | 18 +- components/servo/Cargo.lock | 32 +-- components/style/Cargo.toml | 9 +- components/style/gecko_selector_impl.rs | 28 ++- components/style/lib.rs | 6 +- components/style/matching.rs | 68 +++++- components/style/parser.rs | 3 +- components/style/restyle_hints.rs | 50 +++-- components/style/selector_impl.rs | 35 +++- components/style/selector_matching.rs | 6 +- components/style/servo_selector_impl.rs | 29 ++- ports/cef/Cargo.lock | 28 +-- ports/geckolib/Cargo.lock | 63 ++++-- ports/geckolib/Cargo.toml | 7 +- ports/geckolib/lib.rs | 9 +- ports/geckolib/snapshot.rs | 21 +- ports/geckolib/snapshot_helpers.rs | 2 +- ports/geckolib/string_cache/Cargo.toml | 9 +- ports/geckolib/string_cache/atom_macro.rs | 11 +- ports/geckolib/string_cache/lib.rs | 197 ++++++++++-------- ports/geckolib/wrapper.rs | 39 ++-- tests/unit/style/Cargo.toml | 2 +- 28 files changed, 455 insertions(+), 286 deletions(-) diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index e7c26675e58..a3a3431b912 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -33,7 +33,7 @@ range = {path = "../range"} rustc-serialize = "0.3" script_layout_interface = {path = "../script_layout_interface"} script_traits = {path = "../script_traits"} -selectors = {version = "0.7", features = ["heap_size"]} +selectors = {version = "0.8", features = ["heap_size"]} serde_macros = "0.7.15" smallvec = "0.1" string_cache = {version = "0.2.20", features = ["heap_size"]} diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index b1087e945d7..f9dcd975f9c 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -27,7 +27,7 @@ pub struct RecalcStyleAndConstructFlows<'lc> { impl<'lc, N> DomTraversalContext for RecalcStyleAndConstructFlows<'lc> where N: LayoutNode + TNode, - N::ConcreteElement: ::selectors::Element + N::ConcreteElement: ::selectors::Element { type SharedContext = SharedLayoutContext; diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 891b48f3dd9..75f8ec886cf 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -61,7 +61,7 @@ regex = "0.1.43" rustc-serialize = "0.3" script_layout_interface = {path = "../script_layout_interface"} script_traits = {path = "../script_traits"} -selectors = {version = "0.7", features = ["heap_size"]} +selectors = {version = "0.8", features = ["heap_size"]} serde = "0.7.15" smallvec = "0.1" string_cache = {version = "0.2.20", features = ["heap_size", "unstable"]} diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index b9b02183762..f74f253aa78 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -73,7 +73,6 @@ use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks}; use ref_filter_map::ref_filter_map; use selectors::matching::{DeclarationBlock, ElementFlags, matches}; use selectors::matching::{HAS_SLOW_SELECTOR, HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; -use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes}; use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str}; use std::ascii::AsciiExt; use std::borrow::Cow; @@ -83,9 +82,10 @@ use std::default::Default; use std::mem; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; -use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName}; +use string_cache::{Atom, Namespace, QualName}; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::element_state::*; +use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes}; use style::parser::ParserContextExtraData; use style::properties::DeclaredValue; use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size}; @@ -2235,7 +2235,9 @@ impl VirtualMethods for Element { } impl<'a> ::selectors::MatchAttrGeneric for Root { - fn match_attr(&self, attr: &AttrSelector, test: F) -> bool + type Impl = ServoSelectorImpl; + + fn match_attr(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool { use ::selectors::Element; @@ -2263,8 +2265,6 @@ impl<'a> ::selectors::MatchAttrGeneric for Root { } impl<'a> ::selectors::Element for Root { - type Impl = ServoSelectorImpl; - fn parent_element(&self) -> Option> { self.upcast::().GetParentElement() } @@ -2299,12 +2299,12 @@ impl<'a> ::selectors::Element for Root { }) } - fn get_local_name(&self) -> BorrowedAtom { - BorrowedAtom(self.local_name()) + fn get_local_name(&self) -> &Atom { + self.local_name() } - fn get_namespace(&self) -> BorrowedNamespace { - BorrowedNamespace(self.namespace()) + fn get_namespace(&self) -> &Namespace { + self.namespace() } fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool { diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 544eb00a560..d4518b015e8 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -52,7 +52,7 @@ use selectors::parser::{AttrSelector, NamespaceConstraint}; use std::marker::PhantomData; use std::mem::{transmute, transmute_copy}; use std::sync::Arc; -use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace}; +use string_cache::{Atom, Namespace}; use style::attr::AttrValue; use style::computed_values::display; use style::context::SharedStyleContext; @@ -433,7 +433,10 @@ fn as_element<'le>(node: LayoutJS) -> Option> { } impl<'le> ::selectors::MatchAttrGeneric for ServoLayoutElement<'le> { - fn match_attr(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool { + type Impl = ServoSelectorImpl; + + fn match_attr(&self, attr: &AttrSelector, test: F) -> bool + where F: Fn(&str) -> bool { use ::selectors::Element; let name = if self.is_html_element_in_html_document() { &attr.lower_name @@ -455,8 +458,6 @@ impl<'le> ::selectors::MatchAttrGeneric for ServoLayoutElement<'le> { } impl<'le> ::selectors::Element for ServoLayoutElement<'le> { - type Impl = ServoSelectorImpl; - fn parent_element(&self) -> Option> { unsafe { self.element.upcast().parent_node_ref().and_then(as_element) @@ -516,13 +517,13 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> { } #[inline] - fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a> { - BorrowedAtom(self.element.local_name()) + fn get_local_name(&self) -> &Atom { + self.element.local_name() } #[inline] - fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a> { - BorrowedNamespace(self.element.namespace()) + fn get_namespace(&self) -> &Namespace { + self.element.namespace() } fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool { @@ -823,8 +824,8 @@ impl Iterator for ThreadSafeLayoutNodeChildrenIterator Iterator for ThreadSafeLayoutNodeChildrenIterator ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> { } #[inline] - fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a> { - BorrowedAtom(self.element.local_name()) + fn get_local_name(&self) -> &Atom { + self.element.local_name() } #[inline] - fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a> { - BorrowedNamespace(self.element.namespace()) + fn get_namespace(&self) -> &Namespace { + self.element.namespace() } } @@ -925,7 +926,9 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> { /// Note that the element implementation is needed only for selector matching, /// not for inheritance (styles are inherited appropiately). impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> { - fn match_attr(&self, attr: &AttrSelector, test: F) -> bool + type Impl = ServoSelectorImpl; + + fn match_attr(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool { match attr.namespace { NamespaceConstraint::Specific(ref ns) => { @@ -941,8 +944,6 @@ impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> { } } impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> { - type Impl = ServoSelectorImpl; - fn parent_element(&self) -> Option { warn!("ServoThreadSafeLayoutElement::parent_element called"); None @@ -977,12 +978,12 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> { } #[inline] - fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a> { + fn get_local_name(&self) -> &Atom { ThreadSafeLayoutElement::get_local_name(self) } #[inline] - fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a> { + fn get_namespace(&self) -> &Namespace { ThreadSafeLayoutElement::get_namespace(self) } diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index cbd8d65b72e..0bc63e678ab 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -27,7 +27,7 @@ plugins = {path = "../plugins"} profile_traits = {path = "../profile_traits"} range = {path = "../range"} script_traits = {path = "../script_traits"} -selectors = {version = "0.7", features = ["heap_size"]} +selectors = {version = "0.8", features = ["heap_size"]} string_cache = {version = "0.2.20", features = ["heap_size"]} style = {path = "../style"} url = {version = "1.0.0", features = ["heap_size"]} diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 0f7d4864179..17d948cc8ca 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -11,7 +11,7 @@ use msg::constellation_msg::PipelineId; use range::Range; use restyle_damage::RestyleDamage; use std::sync::Arc; -use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace}; +use string_cache::{Atom, Namespace}; use style::computed_values::display; use style::context::SharedStyleContext; use style::dom::OpaqueNode; @@ -86,7 +86,7 @@ pub trait LayoutNode: TNode { pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq { type ConcreteThreadSafeLayoutElement: ThreadSafeLayoutElement - + ::selectors::Element; + + ::selectors::Element; type ChildrenIterator: Iterator + Sized; /// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode` @@ -158,8 +158,8 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq { #[inline] fn get_details_summary_pseudo(&self) -> Option { if self.is_element() && - self.as_element().get_local_name() == atom!("details") && - self.as_element().get_namespace() == ns!(html) { + self.as_element().get_local_name() == &atom!("details") && + self.as_element().get_namespace() == &ns!(html) { Some(self.with_pseudo(PseudoElementType::DetailsSummary(None))) } else { None @@ -169,8 +169,8 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq { #[inline] fn get_details_content_pseudo(&self) -> Option { if self.is_element() && - self.as_element().get_local_name() == atom!("details") && - self.as_element().get_namespace() == ns!(html) { + self.as_element().get_local_name() == &atom!("details") && + self.as_element().get_namespace() == &ns!(html) { let display = if self.as_element().get_attr(&ns!(), &atom!("open")).is_some() { None // Specified by the stylesheet } else { @@ -351,7 +351,7 @@ pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode { } pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + - ::selectors::Element + + ::selectors::Element + PresentationalHintsSynthetizer { type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode; @@ -359,8 +359,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str>; #[inline] - fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a>; + fn get_local_name(&self) -> &Atom; #[inline] - fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a>; + fn get_namespace(&self) -> &Namespace; } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 94ad472f6bd..3f8ec6e3ac1 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -777,7 +777,7 @@ dependencies = [ "servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "simd 0.1.0 (git+https://github.com/huonw/simd)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -942,7 +942,7 @@ dependencies = [ "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1132,10 +1132,10 @@ dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "script_layout_interface 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1904,10 +1904,10 @@ dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "script_layout_interface 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)", @@ -1941,8 +1941,8 @@ dependencies = [ "profile_traits 0.0.1", "range 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -1989,7 +1989,7 @@ dependencies = [ [[package]] name = "selectors" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2000,7 +2000,7 @@ dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2208,11 +2208,11 @@ dependencies = [ "plugins 0.0.1", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2228,8 +2228,8 @@ dependencies = [ "cssparser 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2698,7 +2698,7 @@ dependencies = [ "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index c2fd71dbb3a..46f62850e60 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -12,11 +12,11 @@ name = "style" path = "lib.rs" [features] -gecko = ["gecko_bindings", "selectors/gecko"] +gecko = ["gecko_bindings", "gecko_string_cache"] servo = ["serde", "serde/nightly", "serde_macros", "heapsize", "heapsize_plugin", "style_traits/servo", "app_units/plugins", "euclid/plugins", "cssparser/heap_size", "cssparser/serde-serialization", - "selectors/heap_size", "selectors/unstable", "string_cache/heap_size", + "selectors/heap_size", "selectors/unstable", "string_cache", "url/heap_size", "plugins"] [dependencies] @@ -28,6 +28,7 @@ encoding = "0.2" euclid = "0.7.1" fnv = "1.0" gecko_bindings = {path = "../../ports/geckolib/gecko_bindings", optional = true} +gecko_string_cache = {path = "../../ports/geckolib/string_cache", optional = true} heapsize = {version = "0.3.0", optional = true} heapsize_plugin = {version = "0.1.2", optional = true} lazy_static = "0.2" @@ -37,11 +38,11 @@ num-traits = "0.1.32" ordered-float = "0.2.2" rand = "0.3" rustc-serialize = "0.3" -selectors = "0.7" +selectors = "0.8.2" serde = {version = "0.7.15", optional = true} serde_macros = {version = "0.7.15", optional = true} smallvec = "0.1" -string_cache = "0.2.20" +string_cache = {version = "0.2.22", features = ["heap_size"], optional = true} style_traits = {path = "../style_traits"} time = "0.1" url = "1.0.0" diff --git a/components/style/gecko_selector_impl.rs b/components/style/gecko_selector_impl.rs index bb763bb11de..0966e157db1 100644 --- a/components/style/gecko_selector_impl.rs +++ b/components/style/gecko_selector_impl.rs @@ -4,8 +4,9 @@ use element_state::ElementState; use selector_impl::PseudoElementCascadeType; -use selectors::parser::{ParserContext, SelectorImpl}; -use string_cache::Atom; +use selector_impl::{attr_exists_selector_is_shareable, attr_equals_selector_is_shareable}; +use selectors::parser::{ParserContext, SelectorImpl, AttrSelector}; +use string_cache::{Atom, WeakAtom}; use stylesheets::Stylesheet; #[derive(Debug, Clone, PartialEq, Eq)] @@ -149,10 +150,27 @@ impl NonTSPseudoClass { } impl SelectorImpl for GeckoSelectorImpl { - type AttrString = Atom; + type AttrValue = Atom; + type Identifier = Atom; + type ClassName = Atom; + type LocalName = Atom; + type Namespace = Atom; + type BorrowedNamespace = WeakAtom; + type BorrowedLocalName = WeakAtom; + type PseudoElement = PseudoElement; type NonTSPseudoClass = NonTSPseudoClass; - fn parse_non_ts_pseudo_class(_context: &ParserContext, + + fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector) -> bool { + attr_exists_selector_is_shareable(attr_selector) + } + + fn attr_equals_selector_is_shareable(attr_selector: &AttrSelector, + value: &Self::AttrValue) -> bool { + attr_equals_selector_is_shareable(attr_selector, value) + } + + fn parse_non_ts_pseudo_class(_context: &ParserContext, name: &str) -> Result { use self::NonTSPseudoClass::*; let pseudo_class = match_ignore_ascii_case! { name, @@ -174,7 +192,7 @@ impl SelectorImpl for GeckoSelectorImpl { Ok(pseudo_class) } - fn parse_pseudo_element(context: &ParserContext, + fn parse_pseudo_element(context: &ParserContext, name: &str) -> Result { use self::AnonBoxPseudoElement::*; use self::PseudoElement::*; diff --git a/components/style/lib.rs b/components/style/lib.rs index e6d87d3e916..1f760aa6d10 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -45,8 +45,8 @@ extern crate deque; extern crate encoding; extern crate euclid; extern crate fnv; -#[cfg(feature = "gecko")] -extern crate gecko_bindings; +#[cfg(feature = "gecko")] extern crate gecko_bindings; +#[cfg(feature = "gecko")] #[macro_use] extern crate gecko_string_cache as string_cache; #[cfg(feature = "servo")] extern crate heapsize; #[allow(unused_extern_crates)] #[macro_use] @@ -63,7 +63,7 @@ extern crate rustc_serialize; extern crate selectors; #[cfg(feature = "servo")] extern crate serde; extern crate smallvec; -#[macro_use(atom, ns)] extern crate string_cache; +#[cfg(feature = "servo")] #[macro_use] extern crate string_cache; #[macro_use] extern crate style_traits; extern crate time; diff --git a/components/style/matching.rs b/components/style/matching.rs index 42613bf8ef4..170534940a7 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -15,12 +15,11 @@ use dom::{TElement, TNode, TRestyleDamage}; use properties::{ComputedValues, PropertyDeclaration, cascade}; use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement}; use selector_matching::{DeclarationBlock, Stylist}; -use selectors::Element; use selectors::bloom::BloomFilter; -use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes}; -use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes}; +use selectors::{Element, MatchAttr}; use sink::ForgetfulSink; use smallvec::SmallVec; +use std::borrow::Borrow; use std::collections::HashMap; use std::hash::{BuildHasherDefault, Hash, Hasher}; use std::slice::Iter; @@ -257,7 +256,7 @@ impl StyleSharingCandidate { } pub fn can_share_style_with(&self, element: &E) -> bool { - if *element.get_local_name() != self.local_name { + if element.get_local_name() != self.local_name.borrow() { return false } @@ -276,7 +275,7 @@ impl StyleSharingCandidate { return false; } - if *element.get_namespace() != self.namespace { + if element.get_namespace() != self.namespace.borrow() { return false } @@ -327,6 +326,61 @@ impl StyleSharingCandidate { } } +bitflags! { + pub flags CommonStyleAffectingAttributes: u8 { + const HIDDEN_ATTRIBUTE = 0x01, + const NO_WRAP_ATTRIBUTE = 0x02, + const ALIGN_LEFT_ATTRIBUTE = 0x04, + const ALIGN_CENTER_ATTRIBUTE = 0x08, + const ALIGN_RIGHT_ATTRIBUTE = 0x10, + } +} + +pub struct CommonStyleAffectingAttributeInfo { + pub atom: Atom, + pub mode: CommonStyleAffectingAttributeMode, +} + +#[derive(Clone)] +pub enum CommonStyleAffectingAttributeMode { + IsPresent(CommonStyleAffectingAttributes), + IsEqual(Atom, CommonStyleAffectingAttributes), +} + +// NB: This must match the order in `selectors::matching::CommonStyleAffectingAttributes`. +#[inline] +pub fn common_style_affecting_attributes() -> [CommonStyleAffectingAttributeInfo; 5] { + [ + CommonStyleAffectingAttributeInfo { + atom: atom!("hidden"), + mode: CommonStyleAffectingAttributeMode::IsPresent(HIDDEN_ATTRIBUTE), + }, + CommonStyleAffectingAttributeInfo { + atom: atom!("nowrap"), + mode: CommonStyleAffectingAttributeMode::IsPresent(NO_WRAP_ATTRIBUTE), + }, + CommonStyleAffectingAttributeInfo { + atom: atom!("align"), + mode: CommonStyleAffectingAttributeMode::IsEqual(atom!("left"), ALIGN_LEFT_ATTRIBUTE), + }, + CommonStyleAffectingAttributeInfo { + atom: atom!("align"), + mode: CommonStyleAffectingAttributeMode::IsEqual(atom!("center"), ALIGN_CENTER_ATTRIBUTE), + }, + CommonStyleAffectingAttributeInfo { + atom: atom!("align"), + mode: CommonStyleAffectingAttributeMode::IsEqual(atom!("right"), ALIGN_RIGHT_ATTRIBUTE), + } + ] +} + +/// Attributes that, if present, disable style sharing. All legacy HTML attributes must be in +/// either this list or `common_style_affecting_attributes`. See the comment in +/// `synthesize_presentational_hints_for_legacy_attributes`. +pub fn rare_style_affecting_attributes() -> [Atom; 3] { + [ atom!("bgcolor"), atom!("border"), atom!("colspan") ] +} + static STYLE_SHARING_CANDIDATE_CACHE_SIZE: usize = 40; impl StyleSharingCandidateCache { @@ -710,7 +764,7 @@ pub trait MatchMethods : TNode { data.style = Some(final_style); - ::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| { + ::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| { let applicable_declarations_for_this_pseudo = applicable_declarations.per_pseudo.get(&pseudo).unwrap(); @@ -718,7 +772,7 @@ pub trait MatchMethods : TNode { // NB: Transitions and animations should only work for // pseudo-elements ::before and ::after let should_animate_properties = - ::Impl::pseudo_is_before_or_after(&pseudo); + ::Impl::pseudo_is_before_or_after(&pseudo); let (new_damage, style) = self.cascade_node_pseudo_element( context, Some(data.style.as_ref().unwrap()), diff --git a/components/style/parser.rs b/components/style/parser.rs index f7aaf97465c..52ce1d9d5fd 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -8,6 +8,7 @@ use cssparser::{Parser, SourcePosition}; use error_reporting::ParseErrorReporter; #[cfg(feature = "gecko")] use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; +use selector_impl::TheSelectorImpl; use selectors::parser::ParserContext as SelectorParserContext; use stylesheets::Origin; use url::Url; @@ -37,7 +38,7 @@ impl ParserContextExtraData { pub struct ParserContext<'a> { pub stylesheet_origin: Origin, pub base_url: &'a Url, - pub selector_context: SelectorParserContext, + pub selector_context: SelectorParserContext, pub error_reporter: Box, pub extra_data: ParserContextExtraData, } diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index b6f08262fe7..4f1467c4584 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -5,13 +5,13 @@ //! Restyle hints: an optimization to avoid unnecessarily matching selectors. use element_state::*; -use selector_impl::{ElementExt, TheSelectorImpl, AttrString, NonTSPseudoClass}; +use selector_impl::{ElementExt, TheSelectorImpl, NonTSPseudoClass, AttrValue}; use selectors::matching::matches_compound_selector; -use selectors::parser::{AttrSelector, Combinator, CompoundSelector, SimpleSelector}; +use selectors::parser::{AttrSelector, Combinator, CompoundSelector, SimpleSelector, SelectorImpl}; use selectors::{Element, MatchAttr}; use std::clone::Clone; use std::sync::Arc; -use string_cache::{Atom, BorrowedAtom, BorrowedNamespace}; +use string_cache::Atom; /// When the ElementState of an element (like IN_HOVER_STATE) changes, certain /// pseudo-classes (like :hover) may require us to restyle that element, its @@ -52,7 +52,7 @@ bitflags! { /// still need to take the ElementWrapper approach for attribute-dependent /// style. So we do it the same both ways for now to reduce complexity, but it's /// worth measuring the performance impact (if any) of the mStateMask approach. -pub trait ElementSnapshot : Sized + MatchAttr { +pub trait ElementSnapshot : Sized + MatchAttr { /// The state of the snapshot, if any. fn state(&self) -> Option; @@ -93,11 +93,11 @@ impl<'a, E> ElementWrapper<'a, E> } impl<'a, E> MatchAttr for ElementWrapper<'a, E> - where E: ElementExt, + where E: ElementExt, { - type AttrString = E::AttrString; + type Impl = TheSelectorImpl; - fn match_attr_has(&self, attr: &AttrSelector) -> bool { + fn match_attr_has(&self, attr: &AttrSelector) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_has(attr), @@ -106,8 +106,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_equals(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_equals(attr, value), @@ -116,8 +116,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_equals_ignore_ascii_case(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_equals_ignore_ascii_case(attr, value), @@ -126,8 +126,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_includes(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_includes(attr, value), @@ -136,8 +136,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_dash(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_dash(attr, value), @@ -146,8 +146,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_prefix(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_prefix(attr, value), @@ -156,8 +156,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_substring(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_substring(attr, value), @@ -166,8 +166,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } fn match_attr_suffix(&self, - attr: &AttrSelector, - value: &Self::AttrString) -> bool { + attr: &AttrSelector, + value: &AttrValue) -> bool { match self.snapshot { Some(snapshot) if snapshot.has_attrs() => snapshot.match_attr_suffix(attr, value), @@ -177,10 +177,8 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E> } impl<'a, E> Element for ElementWrapper<'a, E> - where E: ElementExt + where E: ElementExt { - type Impl = TheSelectorImpl; - fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool { let flag = TheSelectorImpl::pseudo_class_state_flag(&pseudo_class); if flag == ElementState::empty() { @@ -217,11 +215,11 @@ impl<'a, E> Element for ElementWrapper<'a, E> self.element.is_html_element_in_html_document() } - fn get_local_name(&self) -> BorrowedAtom { + fn get_local_name(&self) -> &::BorrowedLocalName { self.element.get_local_name() } - fn get_namespace(&self) -> BorrowedNamespace { + fn get_namespace(&self) -> &::BorrowedNamespace { self.element.get_namespace() } diff --git a/components/style/selector_impl.rs b/components/style/selector_impl.rs index cf846d61f15..276b721ba7f 100644 --- a/components/style/selector_impl.rs +++ b/components/style/selector_impl.rs @@ -4,11 +4,12 @@ //! The pseudo-classes and pseudo-elements supported by the style system. +use matching::{common_style_affecting_attributes, CommonStyleAffectingAttributeMode}; use restyle_hints; use selectors::Element; -use selectors::parser::SelectorImpl; +use selectors::parser::{AttrSelector, SelectorImpl}; -pub type AttrString = ::AttrString; +pub type AttrValue = ::AttrValue; #[cfg(feature = "servo")] pub use servo_selector_impl::*; @@ -69,8 +70,8 @@ impl PseudoElementCascadeType { } } -pub trait ElementExt: Element::AttrString> { - type Snapshot: restyle_hints::ElementSnapshot + 'static; +pub trait ElementExt: Element { + type Snapshot: restyle_hints::ElementSnapshot + 'static; fn is_link(&self) -> bool; } @@ -96,3 +97,29 @@ impl TheSelectorImpl { }) } } + +pub fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector) -> bool { + // NB(pcwalton): If you update this, remember to update the corresponding list in + // `can_share_style_with()` as well. + common_style_affecting_attributes().iter().any(|common_attr_info| { + common_attr_info.atom == attr_selector.name && match common_attr_info.mode { + CommonStyleAffectingAttributeMode::IsPresent(_) => true, + CommonStyleAffectingAttributeMode::IsEqual(..) => false, + } + }) +} + +pub fn attr_equals_selector_is_shareable(attr_selector: &AttrSelector, + value: &AttrValue) -> bool { + // FIXME(pcwalton): Remove once we start actually supporting RTL text. This is in + // here because the UA style otherwise disables all style sharing completely. + atom!("dir") == *value || + common_style_affecting_attributes().iter().any(|common_attr_info| { + common_attr_info.atom == attr_selector.name && match common_attr_info.mode { + CommonStyleAffectingAttributeMode::IsEqual(ref target_value, _) => { + *target_value == *value + } + CommonStyleAffectingAttributeMode::IsPresent(_) => false, + } + }) +} diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 3ed48f6107a..7b18a897d73 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -11,7 +11,7 @@ use keyframes::KeyframesAnimation; use media_queries::{Device, MediaType}; use properties::{self, PropertyDeclaration, PropertyDeclarationBlock, ComputedValues}; use restyle_hints::{RestyleHint, DependencySet}; -use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement, AttrString}; +use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement}; use selectors::Element; use selectors::bloom::BloomFilter; use selectors::matching::DeclarationBlock as GenericDeclarationBlock; @@ -242,7 +242,7 @@ impl Stylist { pseudo: &PseudoElement, parent: &Arc) -> Option> - where E: Element + + where E: Element + PresentationalHintsSynthetizer { debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_lazy()); if self.pseudos_map.get(pseudo).is_none() { @@ -308,7 +308,7 @@ impl Stylist { pseudo_element: Option<&PseudoElement>, applicable_declarations: &mut V) -> bool - where E: Element + + where E: Element + PresentationalHintsSynthetizer, V: Push + VecLike { assert!(!self.is_device_dirty); diff --git a/components/style/servo_selector_impl.rs b/components/style/servo_selector_impl.rs index eb0e539fce4..fab4315dd9f 100644 --- a/components/style/servo_selector_impl.rs +++ b/components/style/servo_selector_impl.rs @@ -8,6 +8,7 @@ use error_reporting::StdoutErrorReporter; use parser::ParserContextExtraData; use restyle_hints::ElementSnapshot; use selector_impl::{ElementExt, PseudoElementCascadeType, TheSelectorImpl}; +use selector_impl::{attr_exists_selector_is_shareable, attr_equals_selector_is_shareable}; use selectors::parser::{AttrSelector, ParserContext, SelectorImpl}; use selectors::{Element, MatchAttrGeneric}; use std::process; @@ -98,11 +99,27 @@ impl NonTSPseudoClass { pub struct ServoSelectorImpl; impl SelectorImpl for ServoSelectorImpl { - type AttrString = String; type PseudoElement = PseudoElement; type NonTSPseudoClass = NonTSPseudoClass; - fn parse_non_ts_pseudo_class(context: &ParserContext, + type AttrValue = String; + type Identifier = Atom; + type ClassName = Atom; + type LocalName = Atom; + type Namespace = Namespace; + type BorrowedLocalName = Atom; + type BorrowedNamespace = Namespace; + + fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector) -> bool { + attr_exists_selector_is_shareable(attr_selector) + } + + fn attr_equals_selector_is_shareable(attr_selector: &AttrSelector, + value: &Self::AttrValue) -> bool { + attr_equals_selector_is_shareable(attr_selector, value) + } + + fn parse_non_ts_pseudo_class(context: &ParserContext, name: &str) -> Result { use self::NonTSPseudoClass::*; let pseudo_class = match_ignore_ascii_case! { name, @@ -132,7 +149,7 @@ impl SelectorImpl for ServoSelectorImpl { Ok(pseudo_class) } - fn parse_pseudo_element(context: &ParserContext, + fn parse_pseudo_element(context: &ParserContext, name: &str) -> Result { use self::PseudoElement::*; let pseudo_element = match_ignore_ascii_case! { name, @@ -257,7 +274,9 @@ impl ElementSnapshot for ServoElementSnapshot { } impl MatchAttrGeneric for ServoElementSnapshot { - fn match_attr(&self, attr: &AttrSelector, test: F) -> bool + type Impl = ServoSelectorImpl; + + fn match_attr(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool { use selectors::parser::NamespaceConstraint; @@ -270,7 +289,7 @@ impl MatchAttrGeneric for ServoElementSnapshot { } } -impl> ElementExt for E { +impl> ElementExt for E { type Snapshot = ServoElementSnapshot; fn is_link(&self) -> bool { diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 1d80f45f89e..b2a898f764b 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -695,7 +695,7 @@ dependencies = [ "servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "simd 0.1.0 (git+https://github.com/huonw/simd)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -851,7 +851,7 @@ dependencies = [ "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1041,10 +1041,10 @@ dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "script_layout_interface 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1758,10 +1758,10 @@ dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "script_layout_interface 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)", @@ -1795,8 +1795,8 @@ dependencies = [ "profile_traits 0.0.1", "range 0.0.1", "script_traits 0.0.1", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -1833,7 +1833,7 @@ dependencies = [ [[package]] name = "selectors" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1844,7 +1844,7 @@ dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2058,7 +2058,7 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2093,11 +2093,11 @@ dependencies = [ "plugins 0.0.1", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2560,7 +2560,7 @@ dependencies = [ "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock index b60e592f554..8b7002cd4c3 100644 --- a/ports/geckolib/Cargo.lock +++ b/ports/geckolib/Cargo.lock @@ -6,12 +6,12 @@ dependencies = [ "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "gecko_bindings 0.0.1", + "gecko_string_cache 0.2.20", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -56,6 +56,14 @@ dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "debug_unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "deque" version = "0.3.1" @@ -154,6 +162,18 @@ dependencies = [ "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gecko_string_cache" +version = "0.2.20" +dependencies = [ + "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gecko_bindings 0.0.1", + "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.14" @@ -263,6 +283,20 @@ dependencies = [ "unreachable 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "phf_generator" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_shared" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quickersort" version = "2.0.1" @@ -304,7 +338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "selectors" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -313,7 +347,7 @@ dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -328,21 +362,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string_cache" -version = "0.2.20" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gecko_bindings 0.0.1", - "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "string_cache" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "string_cache 0.2.20" - [[package]] name = "style" version = "0.0.1" @@ -355,6 +384,7 @@ dependencies = [ "euclid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "gecko_bindings 0.0.1", + "gecko_string_cache 0.2.20", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -364,9 +394,8 @@ dependencies = [ "ordered-float 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml index 8cbe09340a6..10a9f55d264 100644 --- a/ports/geckolib/Cargo.toml +++ b/ports/geckolib/Cargo.toml @@ -14,16 +14,13 @@ app_units = "0.2.5" env_logger = "0.3" euclid = "0.7.1" gecko_bindings = {version = "0.0.1", path = "gecko_bindings"} +gecko_string_cache = {path = "string_cache"} lazy_static = "0.2" libc = "0.2" log = {version = "0.3.5", features = ["release_max_level_info"]} num_cpus = "0.2.2" -selectors = "0.7" -string_cache = {version = "0.2.20", features = ["unstable"]} +selectors = "0.8" style = {path = "../../components/style", features = ["gecko"]} style_traits = {path = "../../components/style_traits"} url = "1.0.0" util = {path = "../../components/util"} - -[replace] -"string_cache:0.2.20" = {path = "string_cache"} diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index c5c31eae733..161f6b0b540 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -6,15 +6,12 @@ extern crate app_units; extern crate env_logger; extern crate euclid; extern crate gecko_bindings; -#[macro_use] -extern crate lazy_static; +#[macro_use] extern crate gecko_string_cache; +#[macro_use] extern crate lazy_static; extern crate libc; -#[macro_use] -extern crate log; +#[macro_use] extern crate log; extern crate num_cpus; extern crate selectors; -#[macro_use(atom, ns)] -extern crate string_cache; extern crate style; extern crate style_traits; extern crate url; diff --git a/ports/geckolib/snapshot.rs b/ports/geckolib/snapshot.rs index 60aba7037e9..0695162f759 100644 --- a/ports/geckolib/snapshot.rs +++ b/ports/geckolib/snapshot.rs @@ -4,11 +4,12 @@ use gecko_bindings::bindings; use gecko_bindings::structs::ServoElementSnapshot; use gecko_bindings::structs::ServoElementSnapshotFlags as Flags; +use gecko_string_cache::Atom; use selectors::parser::AttrSelector; use snapshot_helpers; -use string_cache::Atom; use style::element_state::ElementState; use style::restyle_hints::ElementSnapshot; +use style::selector_impl::TheSelectorImpl; use wrapper::AttrSelectorHelpers; // NB: This is sound, in some sense, because during computation of restyle hints @@ -34,9 +35,9 @@ impl GeckoElementSnapshot { } impl ::selectors::MatchAttr for GeckoElementSnapshot { - type AttrString = Atom; + type Impl = TheSelectorImpl; - fn match_attr_has(&self, attr: &AttrSelector) -> bool { + fn match_attr_has(&self, attr: &AttrSelector) -> bool { unsafe { bindings::Gecko_SnapshotHasAttr(self.0, attr.ns_or_null(), @@ -44,7 +45,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { } } - fn match_attr_equals(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_equals(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrEquals(self.0, attr.ns_or_null(), @@ -54,7 +55,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { } } - fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrEquals(self.0, attr.ns_or_null(), @@ -63,7 +64,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { /* ignoreCase = */ true) } } - fn match_attr_includes(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_includes(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrIncludes(self.0, attr.ns_or_null(), @@ -71,7 +72,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { value.as_ptr()) } } - fn match_attr_dash(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_dash(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrDashEquals(self.0, attr.ns_or_null(), @@ -79,7 +80,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { value.as_ptr()) } } - fn match_attr_prefix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_prefix(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrHasPrefix(self.0, attr.ns_or_null(), @@ -87,7 +88,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { value.as_ptr()) } } - fn match_attr_substring(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_substring(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrHasSubstring(self.0, attr.ns_or_null(), @@ -95,7 +96,7 @@ impl ::selectors::MatchAttr for GeckoElementSnapshot { value.as_ptr()) } } - fn match_attr_suffix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_suffix(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_SnapshotAttrHasSuffix(self.0, attr.ns_or_null(), diff --git a/ports/geckolib/snapshot_helpers.rs b/ports/geckolib/snapshot_helpers.rs index ee7fdd14421..68b2d6d3b45 100644 --- a/ports/geckolib/snapshot_helpers.rs +++ b/ports/geckolib/snapshot_helpers.rs @@ -5,8 +5,8 @@ //! Element an snapshot common logic. use gecko_bindings::structs::nsIAtom; +use gecko_string_cache::Atom; use std::{ptr, slice}; -use string_cache::Atom; pub type ClassOrClassList = unsafe extern fn (T, *mut *mut nsIAtom, *mut *mut *mut nsIAtom) -> u32; diff --git a/ports/geckolib/string_cache/Cargo.toml b/ports/geckolib/string_cache/Cargo.toml index bca87223593..8a7402bbd74 100644 --- a/ports/geckolib/string_cache/Cargo.toml +++ b/ports/geckolib/string_cache/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "string_cache" +name = "gecko_string_cache" description = "A crate to allow using Gecko's nsIAtom as a replacement for string_cache." version = "0.2.20" authors = ["The Servo Project Developers"] @@ -7,17 +7,12 @@ license = "MPL-2.0" publish = false [lib] -name = "string_cache" path = "lib.rs" -[features] -log-events = [] -unstable = [] -heap_size = [] - [dependencies] cfg-if = "0.1.0" gecko_bindings = {version = "0.0.1", path = "../gecko_bindings"} heapsize = "0.3.5" libc = "0.2" +selectors = "0.8" serde = "0.7.15" diff --git a/ports/geckolib/string_cache/atom_macro.rs b/ports/geckolib/string_cache/atom_macro.rs index d5b46482284..c50bc347c18 100644 --- a/ports/geckolib/string_cache/atom_macro.rs +++ b/ports/geckolib/string_cache/atom_macro.rs @@ -1,8 +1,17 @@ use gecko_bindings::structs::nsIAtom; use Atom; +use WeakAtom; -pub fn unsafe_atom_from_static(ptr: *mut nsIAtom) -> Atom { unsafe { Atom::from_static(ptr) } } +// Static atoms have a dummy AddRef/Release, so we don't bother calling +// AddRef() here. This would cause memory corruption with non-static atoms +// both because (a) we wouldn't hold the atom alive, and (b) we can't avoid +// calling Release() when the Atom is dropped, since we can't tell the +// difference between static and non-static atoms without bloating the +// size of Atom beyond word-size. +pub fn unsafe_atom_from_static(ptr: *mut nsIAtom) -> Atom { + Atom(ptr as *mut WeakAtom) +} cfg_if! { if #[cfg(not(target_env = "msvc"))] { diff --git a/ports/geckolib/string_cache/lib.rs b/ports/geckolib/string_cache/lib.rs index 8a6c59f0ca6..e02c14fc60b 100644 --- a/ports/geckolib/string_cache/lib.rs +++ b/ports/geckolib/string_cache/lib.rs @@ -2,10 +2,11 @@ * 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/. */ -#[macro_use] +#[macro_use] #[no_link] extern crate cfg_if; extern crate gecko_bindings; extern crate heapsize; +extern crate selectors; extern crate serde; use gecko_bindings::bindings::Gecko_AddRefAtom; @@ -15,13 +16,15 @@ use gecko_bindings::bindings::Gecko_GetAtomAsUTF16; use gecko_bindings::bindings::Gecko_ReleaseAtom; use gecko_bindings::structs::nsIAtom; use heapsize::HeapSizeOf; +use selectors::bloom::BloomHash; +use selectors::parser::FromCowStr; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::borrow::Cow; -use std::char; +use std::borrow::{Cow, Borrow}; +use std::char::{self, DecodeUtf16}; use std::fmt; use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; -use std::mem::transmute; +use std::iter::Cloned; +use std::mem; use std::ops::Deref; use std::slice; @@ -30,90 +33,88 @@ pub mod atom_macro; #[macro_export] macro_rules! ns { - () => { $crate::Namespace(atom!("")) }; + () => { atom!("") } } +pub type Namespace = Atom; + +#[allow(non_snake_case)] +#[inline] +pub fn Namespace(atom: Atom) -> Atom { + atom +} + +/// A strong reference to a Gecko atom. #[derive(PartialEq, Eq)] -pub struct Atom(*mut nsIAtom); -#[derive(PartialEq, Eq, Debug, Hash, Clone)] -pub struct Namespace(pub Atom); +pub struct Atom(*mut WeakAtom); -pub struct BorrowedAtom<'a> { - weak_ptr: *mut nsIAtom, - chain: PhantomData<&'a ()>, -} +/// An atom *without* a strong reference. +/// +/// Only usable as `&'a WeakAtom`, +/// where `'a` is the lifetime of something that holds a strong reference to that atom. +pub struct WeakAtom(nsIAtom); -impl<'a> BorrowedAtom<'a> { - pub unsafe fn new(atom: *mut nsIAtom) -> Self { - BorrowedAtom { - weak_ptr: atom, - chain: PhantomData, - } - } -} +pub type BorrowedAtom<'a> = &'a WeakAtom; -impl<'a> Deref for BorrowedAtom<'a> { - type Target = Atom; - fn deref(&self) -> &Atom { +impl Deref for Atom { + type Target = WeakAtom; + + #[inline] + fn deref(&self) -> &WeakAtom { unsafe { - transmute(self) + &*self.0 } } } -impl<'a> PartialEq for BorrowedAtom<'a> { - fn eq(&self, other: &Atom) -> bool { - self.weak_ptr == other.as_ptr() +impl Borrow for Atom { + #[inline] + fn borrow(&self) -> &WeakAtom { + self } } -pub struct BorrowedNamespace<'a> { - weak_ptr: *mut nsIAtom, - chain: PhantomData<&'a ()>, -} - -impl<'a> BorrowedNamespace<'a> { - pub unsafe fn new(atom: *mut nsIAtom) -> Self { - BorrowedNamespace { - weak_ptr: atom, - chain: PhantomData, - } - } -} - -impl<'a> Deref for BorrowedNamespace<'a> { - type Target = Namespace; - fn deref(&self) -> &Namespace { - unsafe { - transmute(self) - } - } -} - -impl<'a> PartialEq for BorrowedNamespace<'a> { - fn eq(&self, other: &Namespace) -> bool { - self.weak_ptr == other.0.as_ptr() +impl Eq for WeakAtom {} +impl PartialEq for WeakAtom { + #[inline] + fn eq(&self, other: &Self) -> bool { + let weak: *const WeakAtom = self; + let other: *const WeakAtom = other; + weak == other } } unsafe impl Send for Atom {} unsafe impl Sync for Atom {} +unsafe impl Sync for WeakAtom {} + +impl WeakAtom { + #[inline] + pub unsafe fn new<'a>(atom: *mut nsIAtom) -> &'a mut Self { + &mut *(atom as *mut WeakAtom) + } + + #[inline] + pub fn clone(&self) -> Atom { + Atom::from(self.as_ptr()) + } -impl Atom { pub fn get_hash(&self) -> u32 { - unsafe { - (*self.0).mHash - } + self.0.mHash } pub fn as_slice(&self) -> &[u16] { unsafe { let mut len = 0; - let ptr = Gecko_GetAtomAsUTF16(self.0, &mut len); + let ptr = Gecko_GetAtomAsUTF16(self.as_ptr(), &mut len); slice::from_raw_parts(ptr, len as usize) } } + pub fn chars(&self) -> DecodeUtf16>> { + char::decode_utf16(self.as_slice().iter().cloned()) + } + pub fn with_str(&self, cb: F) -> Output where F: FnOnce(&str) -> Output { // FIXME(bholley): We should measure whether it makes more sense to @@ -124,7 +125,7 @@ impl Atom { pub fn eq_str_ignore_ascii_case(&self, s: &str) -> bool { unsafe { - Gecko_AtomEqualsUTF8IgnoreCase(self.0, s.as_ptr() as *const _, s.len() as u32) + Gecko_AtomEqualsUTF8IgnoreCase(self.as_ptr(), s.as_ptr() as *const _, s.len() as u32) } } @@ -132,29 +133,43 @@ impl Atom { String::from_utf16(self.as_slice()).unwrap() } + #[inline] pub fn as_ptr(&self) -> *mut nsIAtom { - self.0 + let const_ptr: *const nsIAtom = &self.0; + const_ptr as *mut nsIAtom } +} +impl Atom { pub unsafe fn with(ptr: *mut nsIAtom, callback: &mut F) where F: FnMut(&Atom) { - callback(transmute(&ptr)) - } + let atom = Atom(WeakAtom::new(ptr)); + callback(&atom); + mem::forget(atom); + } +} - // Static atoms have a dummy AddRef/Release, so we don't bother calling - // AddRef() here. This would cause memory corruption with non-static atoms - // both because (a) we wouldn't hold the atom alive, and (b) we can't avoid - // calling Release() when the Atom is dropped, since we can't tell the - // difference between static and non-static atoms without bloating the - // size of Atom beyond word-size. - pub unsafe fn from_static(ptr: *mut nsIAtom) -> Atom { - Atom(ptr) +impl BloomHash for Atom { + #[inline] + fn bloom_hash(&self) -> u32 { + self.get_hash() + } +} + +impl BloomHash for WeakAtom { + #[inline] + fn bloom_hash(&self) -> u32 { + self.get_hash() } } impl Hash for Atom { - fn hash(&self, state: &mut H) - where H: Hasher - { + fn hash(&self, state: &mut H) where H: Hasher { + state.write_u32(self.get_hash()); + } +} + +impl Hash for WeakAtom { + fn hash(&self, state: &mut H) where H: Hasher { state.write_u32(self.get_hash()); } } @@ -162,10 +177,7 @@ impl Hash for Atom { impl Clone for Atom { #[inline(always)] fn clone(&self) -> Atom { - unsafe { - Gecko_AddRefAtom(self.0); - } - Atom(self.0) + Atom::from(self.as_ptr()) } } @@ -173,18 +185,19 @@ impl Drop for Atom { #[inline] fn drop(&mut self) { unsafe { - Gecko_ReleaseAtom(self.0); + Gecko_ReleaseAtom(self.as_ptr()); } } } -impl HeapSizeOf for Atom { - fn heap_size_of_children(&self) -> usize { - 0 +impl Default for Atom { + #[inline] + fn default() -> Self { + atom!("") } } -impl HeapSizeOf for Namespace { +impl HeapSizeOf for Atom { fn heap_size_of_children(&self) -> usize { 0 } @@ -222,9 +235,11 @@ impl<'a> From<&'a str> for Atom { #[inline] fn from(string: &str) -> Atom { assert!(string.len() <= u32::max_value() as usize); - Atom(unsafe { - Gecko_Atomize(string.as_ptr() as *const _, string.len() as u32) - }) + unsafe { + Atom(WeakAtom::new( + Gecko_Atomize(string.as_ptr() as *const _, string.len() as u32) + )) + } } } @@ -235,6 +250,13 @@ impl<'a> From> for Atom { } } +impl FromCowStr for Atom { + #[inline] + fn from_cow_str(string: Cow) -> Atom { + Atom::from(&*string) + } +} + impl From for Atom { #[inline] fn from(string: String) -> Atom { @@ -243,10 +265,11 @@ impl From for Atom { } impl From<*mut nsIAtom> for Atom { + #[inline] fn from(ptr: *mut nsIAtom) -> Atom { unsafe { Gecko_AddRefAtom(ptr); - Atom(ptr) + Atom(WeakAtom::new(ptr)) } } } diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index db2df0c6f02..518cc061089 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -26,6 +26,7 @@ use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsEle use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO}; use gecko_bindings::structs::{nsIAtom, nsChangeHint, nsStyleContext}; +use gecko_string_cache::{Atom, Namespace, WeakAtom}; use glue::GeckoDeclarationBlock; use libc::uintptr_t; use selectors::Element; @@ -37,7 +38,6 @@ use std::marker::PhantomData; use std::ops::BitOr; use std::ptr; use std::sync::Arc; -use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace}; use style::data::PrivateStyleData; use style::dom::{OpaqueNode, PresentationalHintsSynthetizer}; use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode}; @@ -433,7 +433,7 @@ impl<'le> TElement for GeckoElement<'le> { fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool { unsafe { bindings::Gecko_HasAttr(self.element, - namespace.0.as_ptr(), + namespace.as_ptr(), attr.as_ptr()) } } @@ -442,7 +442,7 @@ impl<'le> TElement for GeckoElement<'le> { fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool { unsafe { bindings::Gecko_AttrEquals(self.element, - namespace.0.as_ptr(), + namespace.as_ptr(), attr.as_ptr(), val.as_ptr(), /* ignoreCase = */ false) @@ -459,8 +459,6 @@ impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> { } impl<'le> ::selectors::Element for GeckoElement<'le> { - type Impl = GeckoSelectorImpl; - fn parent_element(&self) -> Option { unsafe { Gecko_GetParentElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el)) @@ -502,15 +500,15 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { false } - fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a> { + fn get_local_name(&self) -> &WeakAtom { unsafe { - BorrowedAtom::new(Gecko_LocalName(self.element)) + WeakAtom::new(Gecko_LocalName(self.element)) } } - fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a> { + fn get_namespace(&self) -> &WeakAtom { unsafe { - BorrowedNamespace::new(Gecko_Namespace(self.element)) + WeakAtom::new(Gecko_Namespace(self.element)) } } @@ -575,11 +573,11 @@ pub trait AttrSelectorHelpers { fn select_name(&self, is_html_element_in_html_document: bool) -> *mut nsIAtom; } -impl AttrSelectorHelpers for AttrSelector { +impl AttrSelectorHelpers for AttrSelector { fn ns_or_null(&self) -> *mut nsIAtom { match self.namespace { NamespaceConstraint::Any => ptr::null_mut(), - NamespaceConstraint::Specific(ref ns) => ns.0.as_ptr(), + NamespaceConstraint::Specific(ref ns) => ns.as_ptr(), } } @@ -593,15 +591,16 @@ impl AttrSelectorHelpers for AttrSelector { } impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { - type AttrString = Atom; - fn match_attr_has(&self, attr: &AttrSelector) -> bool { + type Impl = GeckoSelectorImpl; + + fn match_attr_has(&self, attr: &AttrSelector) -> bool { unsafe { bindings::Gecko_HasAttr(self.element, attr.ns_or_null(), attr.select_name(self.is_html_element_in_html_document())) } } - fn match_attr_equals(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_equals(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrEquals(self.element, attr.ns_or_null(), @@ -610,7 +609,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { /* ignoreCase = */ false) } } - fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrEquals(self.element, attr.ns_or_null(), @@ -619,7 +618,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { /* ignoreCase = */ false) } } - fn match_attr_includes(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_includes(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrIncludes(self.element, attr.ns_or_null(), @@ -627,7 +626,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { value.as_ptr()) } } - fn match_attr_dash(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_dash(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrDashEquals(self.element, attr.ns_or_null(), @@ -635,7 +634,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { value.as_ptr()) } } - fn match_attr_prefix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_prefix(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrHasPrefix(self.element, attr.ns_or_null(), @@ -643,7 +642,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { value.as_ptr()) } } - fn match_attr_substring(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_substring(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrHasSubstring(self.element, attr.ns_or_null(), @@ -651,7 +650,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> { value.as_ptr()) } } - fn match_attr_suffix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool { + fn match_attr_suffix(&self, attr: &AttrSelector, value: &Atom) -> bool { unsafe { bindings::Gecko_AttrHasSuffix(self.element, attr.ns_or_null(), diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml index ca9cfe780c4..844b8ad31b9 100644 --- a/tests/unit/style/Cargo.toml +++ b/tests/unit/style/Cargo.toml @@ -14,7 +14,7 @@ app_units = "0.2.5" cssparser = {version = "0.5.4", features = ["heap_size"]} euclid = "0.7.1" rustc-serialize = "0.3" -selectors = {version = "0.7", features = ["heap_size"]} +selectors = {version = "0.8", features = ["heap_size"]} string_cache = {version = "0.2", features = ["heap_size"]} style = {path = "../../../components/style"} style_traits = {path = "../../../components/style_traits"}