aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/Cargo.toml2
-rw-r--r--components/layout/traversal.rs2
-rw-r--r--components/script/Cargo.toml2
-rw-r--r--components/script/dom/element.rs53
-rw-r--r--components/script/layout_wrapper.rs90
-rw-r--r--components/script_layout_interface/Cargo.toml2
-rw-r--r--components/script_layout_interface/wrapper_traits.rs4
-rw-r--r--components/servo/Cargo.lock12
-rw-r--r--components/style/Cargo.toml4
-rw-r--r--components/style/dom.rs4
-rw-r--r--components/style/matching.rs64
-rw-r--r--components/style/properties/longhand/box.mako.rs3
-rw-r--r--components/style/properties/longhand/position.mako.rs5
-rw-r--r--components/style/properties/properties.mako.rs2
-rw-r--r--components/style/restyle_hints.rs117
-rw-r--r--components/style/selector_impl.rs3
-rw-r--r--components/style/selector_matching.rs34
-rw-r--r--ports/cef/Cargo.lock10
-rw-r--r--ports/geckolib/Cargo.lock6
-rw-r--r--ports/geckolib/Cargo.toml2
-rw-r--r--ports/geckolib/data.rs16
-rw-r--r--ports/geckolib/gecko_bindings/bindings.rs24
-rw-r--r--ports/geckolib/gecko_bindings/structs_debug.rs52
-rw-r--r--ports/geckolib/gecko_bindings/structs_release.rs52
-rw-r--r--ports/geckolib/glue.rs15
-rw-r--r--ports/geckolib/lib.rs4
-rw-r--r--ports/geckolib/selector_impl.rs2
-rw-r--r--ports/geckolib/wrapper.rs126
-rw-r--r--tests/unit/style/Cargo.toml2
29 files changed, 445 insertions, 269 deletions
diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml
index 188b39e9207..05f9fcda82c 100644
--- a/components/layout/Cargo.toml
+++ b/components/layout/Cargo.toml
@@ -31,7 +31,7 @@ range = {path = "../range"}
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
-selectors = {version = "0.6", features = ["heap_size"]}
+selectors = {version = "0.7", features = ["heap_size"]}
serde_macros = "0.7.11"
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 5db766f68b5..581fee5e03d 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -28,7 +28,7 @@ pub struct RecalcStyleAndConstructFlows<'lc> {
impl<'lc, N> DomTraversalContext<N> for RecalcStyleAndConstructFlows<'lc>
where N: LayoutNode + TNode<ConcreteComputedValues=ServoComputedValues>,
- N::ConcreteElement: ::selectors::Element<Impl=ServoSelectorImpl>
+ N::ConcreteElement: ::selectors::Element<Impl=ServoSelectorImpl, AttrString=String>
{
type SharedContext = SharedLayoutContext;
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index d9bdeac843b..fa2d75c633d 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -57,7 +57,7 @@ regex = "0.1.43"
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
-selectors = {version = "0.6", features = ["heap_size"]}
+selectors = {version = "0.7", features = ["heap_size"]}
serde = "0.7.11"
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 d9535663d46..e53f7dbb77b 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -2217,6 +2217,34 @@ impl VirtualMethods for Element {
}
}
+impl<'a> ::selectors::MatchAttrGeneric for Root<Element> {
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
+ where F: Fn(&str) -> bool
+ {
+ use ::selectors::Element;
+ let local_name = {
+ if self.is_html_element_in_html_document() {
+ &attr.lower_name
+ } else {
+ &attr.name
+ }
+ };
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attribute(ns, local_name)
+ .map_or(false, |attr| {
+ test(&attr.value())
+ })
+ },
+ NamespaceConstraint::Any => {
+ self.attrs.borrow().iter().any(|attr| {
+ attr.local_name() == local_name && test(&attr.value())
+ })
+ }
+ }
+ }
+}
+
impl<'a> ::selectors::Element for Root<Element> {
type Impl = ServoSelectorImpl;
@@ -2317,31 +2345,6 @@ impl<'a> ::selectors::Element for Root<Element> {
}
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
- where F: Fn(&str) -> bool
- {
- let local_name = {
- if self.is_html_element_in_html_document() {
- &attr.lower_name
- } else {
- &attr.name
- }
- };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attribute(ns, local_name)
- .map_or(false, |attr| {
- test(&attr.value())
- })
- },
- NamespaceConstraint::Any => {
- self.attrs.borrow().iter().any(|attr| {
- attr.local_name() == local_name && test(&attr.value())
- })
- }
- }
- }
-
fn is_html_element_in_html_document(&self) -> bool {
self.html_element_in_html_document()
}
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 7085fcae002..ebc2da9c529 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -387,17 +387,13 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
#[inline]
- fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
- }
+ fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool {
+ self.get_attr(namespace, attr).is_some()
}
#[inline]
- fn get_attrs(&self, name: &Atom) -> Vec<&str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
- }
+ fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool {
+ self.get_attr(namespace, attr).map_or(false, |x| x == val)
}
}
@@ -409,12 +405,41 @@ impl<'le> ServoLayoutElement<'le> {
chain: PhantomData,
}
}
+
+ #[inline]
+ fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str> {
+ unsafe {
+ (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
+ }
+ }
}
fn as_element<'le>(node: LayoutJS<Node>) -> Option<ServoLayoutElement<'le>> {
node.downcast().map(ServoLayoutElement::from_layout_js)
}
+impl<'le> ::selectors::MatchAttrGeneric for ServoLayoutElement<'le> {
+ fn match_attr<F>(&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
+ } else {
+ &attr.name
+ };
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attr(ns, name).map_or(false, |attr| test(attr))
+ },
+ NamespaceConstraint::Any => {
+ let attrs = unsafe {
+ (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
+ };
+ attrs.iter().any(|attr| test(*attr))
+ }
+ }
+ }
+}
+
impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
type Impl = ServoSelectorImpl;
@@ -550,22 +575,6 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
}
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
- let name = if self.is_html_element_in_html_document() {
- &attr.lower_name
- } else {
- &attr.name
- };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attr(ns, name).map_or(false, |attr| test(attr))
- },
- NamespaceConstraint::Any => {
- self.get_attrs(name).iter().any(|attr| test(*attr))
- }
- }
- }
-
fn is_html_element_in_html_document(&self) -> bool {
unsafe {
self.element.html_element_in_html_document_for_layout()
@@ -900,7 +909,23 @@ 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::Element for ServoThreadSafeLayoutElement<'le> {
+impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> {
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
+ where F: Fn(&str) -> bool {
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attr(ns, &attr.name).map_or(false, |attr| test(attr))
+ },
+ NamespaceConstraint::Any => {
+ unsafe {
+ self.element.get_attr_vals_for_layout(&attr.name).iter()
+ .any(|attr| test(*attr))
+ }
+ }
+ }
+ }
+}
+impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
type Impl = ServoSelectorImpl;
fn parent_element(&self) -> Option<Self> {
@@ -962,21 +987,6 @@ impl <'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
false
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
- where F: Fn(&str) -> bool {
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attr(ns, &attr.name).map_or(false, |attr| test(attr))
- },
- NamespaceConstraint::Any => {
- unsafe {
- self.element.get_attr_vals_for_layout(&attr.name).iter()
- .any(|attr| test(*attr))
- }
- }
- }
- }
-
fn is_empty(&self) -> bool {
warn!("ServoThreadSafeLayoutElement::is_empty called");
false
diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml
index 51b767c753f..41c1f6e2598 100644
--- a/components/script_layout_interface/Cargo.toml
+++ b/components/script_layout_interface/Cargo.toml
@@ -26,7 +26,7 @@ plugins = {path = "../plugins"}
profile_traits = {path = "../profile_traits"}
range = {path = "../range"}
script_traits = {path = "../script_traits"}
-selectors = {version = "0.6", features = ["heap_size"]}
+selectors = {version = "0.7", 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 a816321ec28..bdbf31c37c8 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -86,7 +86,7 @@ pub trait LayoutNode: TNode {
pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
type ConcreteThreadSafeLayoutElement:
ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>
- + ::selectors::Element<Impl=ServoSelectorImpl>;
+ + ::selectors::Element<Impl=ServoSelectorImpl, AttrString=String>;
type ChildrenIterator: Iterator<Item = Self> + Sized;
/// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
@@ -351,7 +351,7 @@ pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
}
pub trait ThreadSafeLayoutElement: Clone + Copy + Sized +
- ::selectors::Element<Impl=ServoSelectorImpl> +
+ ::selectors::Element<Impl=ServoSelectorImpl, AttrString=String> +
PresentationalHintsSynthetizer {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 3424416cead..997fc8ab250 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -1159,7 +1159,7 @@ 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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1942,7 +1942,7 @@ 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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1978,7 +1978,7 @@ dependencies = [
"profile_traits 0.0.1",
"range 0.0.1",
"script_traits 0.0.1",
- "selectors 0.6.0 (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)",
"style 0.0.1",
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2026,7 +2026,7 @@ dependencies = [
[[package]]
name = "selectors"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2243,7 +2243,7 @@ dependencies = [
"num-traits 0.1.32 (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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2263,7 +2263,7 @@ 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.6.0 (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)",
"style 0.0.1",
"style_traits 0.0.1",
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index a90673b9e40..049dd560eeb 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -11,7 +11,7 @@ name = "style"
path = "lib.rs"
[features]
-gecko = ["gecko_bindings"]
+gecko = ["gecko_bindings", "selectors/gecko"]
servo = ["serde", "serde/nightly", "serde_macros", "heapsize", "heapsize_plugin",
"style_traits/servo", "app_units/plugins", "euclid/plugins",
"cssparser/heap_size", "cssparser/serde-serialization",
@@ -36,7 +36,7 @@ matches = "0.1"
num-traits = "0.1.32"
rand = "0.3"
rustc-serialize = "0.3"
-selectors = "0.6"
+selectors = "0.7"
serde = {version = "0.7.11", optional = true}
serde_macros = {version = "0.7.11", optional = true}
smallvec = "0.1"
diff --git a/components/style/dom.rs b/components/style/dom.rs
index 11cc5f93a0e..0e94c2c5c1d 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -207,8 +207,8 @@ pub trait TElement : Sized + Copy + Clone + ElementExt + PresentationalHintsSynt
fn get_state(&self) -> ElementState;
- fn get_attr<'a>(&'a self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
- fn get_attrs<'a>(&'a self, attr: &Atom) -> Vec<&'a str>;
+ fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool;
+ fn attr_equals(&self, namespace: &Namespace, attr: &Atom, value: &Atom) -> bool;
/// Properly marks nodes as dirty in response to restyle hints.
fn note_restyle_hint(&self, mut hint: RestyleHint) {
diff --git a/components/style/matching.rs b/components/style/matching.rs
index d3dd3742d3d..5d4fa82b8ce 100644
--- a/components/style/matching.rs
+++ b/components/style/matching.rs
@@ -34,16 +34,13 @@ fn create_common_style_affecting_attributes_from_element<E: TElement>(element: &
for attribute_info in &common_style_affecting_attributes() {
match attribute_info.mode {
CommonStyleAffectingAttributeMode::IsPresent(flag) => {
- if element.get_attr(&ns!(), &attribute_info.atom).is_some() {
+ if element.has_attr(&ns!(), &attribute_info.atom) {
flags.insert(flag)
}
}
- CommonStyleAffectingAttributeMode::IsEqual(target_value, flag) => {
- match element.get_attr(&ns!(), &attribute_info.atom) {
- Some(element_value) if element_value == target_value => {
- flags.insert(flag)
- }
- _ => {}
+ CommonStyleAffectingAttributeMode::IsEqual(ref target_value, flag) => {
+ if element.attr_equals(&ns!(), &attribute_info.atom, target_value) {
+ flags.insert(flag)
}
}
}
@@ -189,8 +186,7 @@ pub struct StyleSharingCandidate<C: ComputedValues> {
pub style: Arc<C>,
pub parent_style: Arc<C>,
pub local_name: Atom,
- // FIXME(pcwalton): Should be a list of atoms instead.
- pub class: Option<String>,
+ pub classes: Vec<Atom>,
pub namespace: Namespace,
pub common_style_affecting_attributes: CommonStyleAffectingAttributes,
pub link: bool,
@@ -201,7 +197,7 @@ impl<C: ComputedValues> PartialEq for StyleSharingCandidate<C> {
arc_ptr_eq(&self.style, &other.style) &&
arc_ptr_eq(&self.parent_style, &other.parent_style) &&
self.local_name == other.local_name &&
- self.class == other.class &&
+ self.classes == other.classes &&
self.link == other.link &&
self.namespace == other.namespace &&
self.common_style_affecting_attributes == other.common_style_affecting_attributes
@@ -246,12 +242,13 @@ impl<C: ComputedValues> StyleSharingCandidate<C> {
return None
}
+ let mut classes = Vec::new();
+ element.each_class(|c| classes.push(c.clone()));
Some(StyleSharingCandidate {
style: style,
parent_style: parent_style,
local_name: element.get_local_name().clone(),
- class: element.get_attr(&ns!(), &atom!("class"))
- .map(|string| string.to_owned()),
+ classes: classes,
link: element.is_link(),
namespace: (*element.get_namespace()).clone(),
common_style_affecting_attributes:
@@ -264,14 +261,19 @@ impl<C: ComputedValues> StyleSharingCandidate<C> {
return false
}
- // FIXME(pcwalton): Use `each_class` here instead of slow string comparison.
- match (&self.class, element.get_attr(&ns!(), &atom!("class"))) {
- (&None, Some(_)) | (&Some(_), None) => return false,
- (&Some(ref this_class), Some(element_class)) if
- element_class != &**this_class => {
- return false
+ let mut num_classes = 0;
+ let mut classes_match = true;
+ element.each_class(|c| {
+ num_classes += 1;
+ // Note that we could do this check more cheaply if we decided to
+ // only consider class lists as equal if the orders match, since
+ // we could then index by num_classes instead of using .contains().
+ if classes_match && !self.classes.contains(c) {
+ classes_match = false;
}
- (&Some(_), Some(_)) | (&None, None) => {}
+ });
+ if !classes_match || num_classes != self.classes.len() {
+ return false;
}
if *element.get_namespace() != self.namespace {
@@ -291,31 +293,25 @@ impl<C: ComputedValues> StyleSharingCandidate<C> {
match attribute_info.mode {
CommonStyleAffectingAttributeMode::IsPresent(flag) => {
if self.common_style_affecting_attributes.contains(flag) !=
- element.get_attr(&ns!(), &attribute_info.atom).is_some() {
+ element.has_attr(&ns!(), &attribute_info.atom) {
return false
}
}
- CommonStyleAffectingAttributeMode::IsEqual(target_value, flag) => {
- match element.get_attr(&ns!(), &attribute_info.atom) {
- Some(ref element_value) if self.common_style_affecting_attributes
- .contains(flag) &&
- *element_value != target_value => {
+ CommonStyleAffectingAttributeMode::IsEqual(ref target_value, flag) => {
+ let contains = self.common_style_affecting_attributes.contains(flag);
+ if element.has_attr(&ns!(), &attribute_info.atom) {
+ if !contains || !element.attr_equals(&ns!(), &attribute_info.atom, target_value) {
return false
}
- Some(_) if !self.common_style_affecting_attributes.contains(flag) => {
- return false
- }
- None if self.common_style_affecting_attributes.contains(flag) => {
- return false
- }
- _ => {}
+ } else if contains {
+ return false
}
}
}
}
for attribute_name in &rare_style_affecting_attributes() {
- if element.get_attr(&ns!(), attribute_name).is_some() {
+ if element.has_attr(&ns!(), attribute_name) {
return false
}
}
@@ -601,7 +597,7 @@ pub trait ElementMatchMethods : TElement
if self.style_attribute().is_some() {
return StyleSharingResult::CannotShare
}
- if self.get_attr(&ns!(), &atom!("id")).is_some() {
+ if self.has_attr(&ns!(), &atom!("id")) {
return StyleSharingResult::CannotShare
}
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index 580926889be..381ca4df1d9 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -94,8 +94,7 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
<%helpers:single_keyword_computed name="float"
values="none left right"
animatable="False"
- need_clone="True"
- gecko_ffi_name="mFloats">
+ need_clone="True">
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs
index a143dab44c5..3ad07a9c2c3 100644
--- a/components/style/properties/longhand/position.mako.rs
+++ b/components/style/properties/longhand/position.mako.rs
@@ -77,11 +77,14 @@ ${helpers.single_keyword("justify-content", "flex-start flex-end center space-be
products="servo",
animatable=False)}
+// FIXME(heycam): Disable align-items in geckolib since we don't support the Gecko initial value
+// 'normal' yet.
${helpers.single_keyword("align-items", "stretch flex-start flex-end center baseline",
experimental=True,
need_clone=True,
gecko_constant_prefix="NS_STYLE_ALIGN",
- animatable=False)}
+ animatable=False,
+ products="servo")}
${helpers.single_keyword("align-content", "stretch flex-start flex-end center space-between space-around",
experimental=True,
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index d2d07c79a73..c5b08b44aac 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -1921,6 +1921,7 @@ pub fn cascade<C: ComputedValues>(
}
}
+ % if "align-items" in data.longhands_by_name:
{
use self::style_struct_traits::Position;
use computed_values::align_self::T as align_self;
@@ -1937,6 +1938,7 @@ pub fn cascade<C: ComputedValues>(
style.mutate_position().set_align_self(self_align);
}
}
+ % endif
// The initial value of border-*-width may be changed at computed value time.
% for side in ["top", "right", "bottom", "left"]:
diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs
index c517a6f1a7b..cd9957322e4 100644
--- a/components/style/restyle_hints.rs
+++ b/components/style/restyle_hints.rs
@@ -7,9 +7,9 @@
use attr::{AttrIdentifier, AttrValue};
use element_state::*;
use selector_impl::SelectorImplExt;
-use selectors::Element;
use selectors::matching::matches_compound_selector;
use selectors::parser::{AttrSelector, Combinator, CompoundSelector, SelectorImpl, SimpleSelector};
+use selectors::{Element, MatchAttrGeneric};
use std::clone::Clone;
use std::sync::Arc;
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
@@ -81,15 +81,21 @@ impl ElementSnapshot {
static EMPTY_SNAPSHOT: ElementSnapshot = ElementSnapshot { state: None, attrs: None };
+// FIXME(bholley): This implementation isn't going to work for geckolib, because
+// it's fundamentally based on get_attr/match_attr, which we don't want to support
+// that configuration due to the overhead of converting between UTF-16 and UTF-8.
+// We'll need to figure something out when we start using restyle hints with
+// geckolib, but in the mean time we can just use the trait parameters to
+// specialize it to the Servo configuration.
struct ElementWrapper<'a, E>
- where E: Element,
+ where E: Element<AttrString=String>,
E::Impl: SelectorImplExt {
element: E,
snapshot: &'a ElementSnapshot,
}
impl<'a, E> ElementWrapper<'a, E>
- where E: Element,
+ where E: Element<AttrString=String>,
E::Impl: SelectorImplExt {
pub fn new(el: E) -> ElementWrapper<'a, E> {
ElementWrapper { element: el, snapshot: &EMPTY_SNAPSHOT }
@@ -100,8 +106,42 @@ impl<'a, E> ElementWrapper<'a, E>
}
}
+#[cfg(not(feature = "gecko"))]
+impl<'a, E> MatchAttrGeneric for ElementWrapper<'a, E>
+ where E: Element<AttrString=String>,
+ E: MatchAttrGeneric,
+ E::Impl: SelectorImplExt {
+ 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();
+ let local_name = if html { &attr.lower_name } else { &attr.name };
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => self.snapshot.get_attr(ns, local_name),
+ NamespaceConstraint::Any => self.snapshot.get_attr_ignore_ns(local_name),
+ }.map_or(false, |v| test(v))
+ },
+ None => self.element.match_attr(attr, test)
+ }
+ }
+}
+
+#[cfg(feature = "gecko")]
+impl<'a, E> MatchAttrGeneric for ElementWrapper<'a, E>
+ where E: Element<AttrString=String>,
+ E: MatchAttrGeneric,
+ E::Impl: SelectorImplExt {
+ fn match_attr<F>(&self, _: &AttrSelector, _: F) -> bool
+ where F: Fn(&str) -> bool {
+ panic!("Not implemented for Gecko - this system will need to be redesigned");
+ }
+}
+
impl<'a, E> Element for ElementWrapper<'a, E>
- where E: Element,
+ where E: Element<AttrString=String>,
+ E: MatchAttrGeneric,
E::Impl: SelectorImplExt {
type Impl = E::Impl;
@@ -155,27 +195,6 @@ 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();
- let local_name = if html { &attr.lower_name } else { &attr.name };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => self.snapshot.get_attr(ns, local_name),
- NamespaceConstraint::Any => self.snapshot.get_attr_ignore_ns(local_name),
- }.map_or(false, |v| test(v))
- },
- None => self.element.match_attr(attr, test)
- }
- }
fn is_empty(&self) -> bool {
self.element.is_empty()
}
@@ -208,7 +227,7 @@ fn is_attr_selector<Impl: SelectorImpl>(sel: &SimpleSelector<Impl>) -> bool {
SimpleSelector::AttrExists(_) |
SimpleSelector::AttrEqual(_, _, _) |
SimpleSelector::AttrIncludes(_, _) |
- SimpleSelector::AttrDashMatch(_, _, _) |
+ SimpleSelector::AttrDashMatch(_, _) |
SimpleSelector::AttrPrefixMatch(_, _) |
SimpleSelector::AttrSubstringMatch(_, _) |
SimpleSelector::AttrSuffixMatch(_, _) => true,
@@ -285,28 +304,6 @@ impl<Impl: SelectorImplExt> DependencySet<Impl> {
DependencySet { deps: Vec::new() }
}
- pub fn compute_hint<E>(&self, el: &E, snapshot: &ElementSnapshot, current_state: ElementState)
- -> RestyleHint
- where E: Element<Impl=Impl> + Clone {
- let state_changes = snapshot.state.map_or(ElementState::empty(), |old_state| current_state ^ old_state);
- let attrs_changed = snapshot.attrs.is_some();
- let mut hint = RestyleHint::empty();
- for dep in &self.deps {
- if state_changes.intersects(dep.sensitivities.states) || (attrs_changed && dep.sensitivities.attrs) {
- let old_el: ElementWrapper<E> = ElementWrapper::new_with_snapshot(el.clone(), snapshot);
- let matched_then = matches_compound_selector(&*dep.selector, &old_el, None, &mut false);
- let matches_now = matches_compound_selector(&*dep.selector, el, None, &mut false);
- if matched_then != matches_now {
- hint.insert(combinator_to_restyle_hint(dep.combinator));
- if hint.is_all() {
- break
- }
- }
- }
- }
- hint
- }
-
pub fn note_selector(&mut self, selector: Arc<CompoundSelector<Impl>>) {
let mut cur = selector;
let mut combinator: Option<Combinator> = None;
@@ -340,3 +337,27 @@ impl<Impl: SelectorImplExt> DependencySet<Impl> {
self.deps.clear();
}
}
+
+impl<Impl: SelectorImplExt<AttrString=String>> DependencySet<Impl> {
+ pub fn compute_hint<E>(&self, el: &E, snapshot: &ElementSnapshot, current_state: ElementState)
+ -> RestyleHint
+ where E: Element<Impl=Impl, AttrString=Impl::AttrString> + Clone + MatchAttrGeneric {
+ let state_changes = snapshot.state.map_or(ElementState::empty(), |old_state| current_state ^ old_state);
+ let attrs_changed = snapshot.attrs.is_some();
+ let mut hint = RestyleHint::empty();
+ for dep in &self.deps {
+ if state_changes.intersects(dep.sensitivities.states) || (attrs_changed && dep.sensitivities.attrs) {
+ let old_el: ElementWrapper<E> = ElementWrapper::new_with_snapshot(el.clone(), snapshot);
+ let matched_then = matches_compound_selector(&*dep.selector, &old_el, None, &mut false);
+ let matches_now = matches_compound_selector(&*dep.selector, el, None, &mut false);
+ if matched_then != matches_now {
+ hint.insert(combinator_to_restyle_hint(dep.combinator));
+ if hint.is_all() {
+ break
+ }
+ }
+ }
+ }
+ hint
+ }
+}
diff --git a/components/style/selector_impl.rs b/components/style/selector_impl.rs
index cf95f4a9048..cd47d0dc7f5 100644
--- a/components/style/selector_impl.rs
+++ b/components/style/selector_impl.rs
@@ -181,6 +181,7 @@ impl NonTSPseudoClass {
pub struct ServoSelectorImpl;
impl SelectorImpl for ServoSelectorImpl {
+ type AttrString = String;
type PseudoElement = PseudoElement;
type NonTSPseudoClass = NonTSPseudoClass;
@@ -278,7 +279,7 @@ impl SelectorImplExt for ServoSelectorImpl {
}
}
-impl<E: Element<Impl=ServoSelectorImpl>> ElementExt for E {
+impl<E: Element<Impl=ServoSelectorImpl, AttrString=String>> ElementExt for E {
fn is_link(&self) -> bool {
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
}
diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs
index 74718d4b69b..b632d783e1e 100644
--- a/components/style/selector_matching.rs
+++ b/components/style/selector_matching.rs
@@ -13,11 +13,11 @@ use parser::ParserContextExtraData;
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
use selector_impl::{SelectorImplExt, ServoSelectorImpl};
-use selectors::Element;
use selectors::bloom::BloomFilter;
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
use selectors::matching::{Rule, SelectorMap};
use selectors::parser::SelectorImpl;
+use selectors::{Element, MatchAttrGeneric};
use sink::Push;
use smallvec::VecLike;
use std::collections::HashMap;
@@ -311,7 +311,7 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
pseudo: &Impl::PseudoElement,
parent: &Arc<Impl::ComputedValues>)
-> Option<Arc<Impl::ComputedValues>>
- where E: Element<Impl=Impl> +
+ where E: Element<Impl=Impl, AttrString=Impl::AttrString> +
PresentationalHintsSynthetizer {
debug_assert!(Impl::pseudo_element_cascade_type(pseudo).is_lazy());
if self.pseudos_map.get(pseudo).is_none() {
@@ -336,18 +336,6 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
Some(Arc::new(computed))
}
- pub fn compute_restyle_hint<E>(&self, element: &E,
- snapshot: &ElementSnapshot,
- // NB: We need to pass current_state as an argument because
- // selectors::Element doesn't provide access to ElementState
- // directly, and computing it from the ElementState would be
- // more expensive than getting it directly from the caller.
- current_state: ElementState)
- -> RestyleHint
- where E: Element<Impl=Impl> + Clone {
- self.state_deps.compute_hint(element, snapshot, current_state)
- }
-
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet<Impl>>]) {
let cascaded_rule = stylesheets.iter()
.flat_map(|s| s.effective_rules(&self.device).viewport())
@@ -389,7 +377,8 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
pseudo_element: Option<&Impl::PseudoElement>,
applicable_declarations: &mut V)
-> bool
- where E: Element<Impl=Impl> + PresentationalHintsSynthetizer,
+ where E: Element<Impl=Impl, AttrString=Impl::AttrString> +
+ PresentationalHintsSynthetizer,
V: Push<DeclarationBlock> + VecLike<DeclarationBlock> {
assert!(!self.is_device_dirty);
assert!(style_attribute.is_none() || pseudo_element.is_none(),
@@ -474,6 +463,21 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
}
}
+impl<Impl: SelectorImplExt<AttrString=String>> Stylist<Impl> {
+ pub fn compute_restyle_hint<E>(&self, element: &E,
+ snapshot: &ElementSnapshot,
+ // NB: We need to pass current_state as an argument because
+ // selectors::Element doesn't provide access to ElementState
+ // directly, and computing it from the ElementState would be
+ // more expensive than getting it directly from the caller.
+ current_state: ElementState)
+ -> RestyleHint
+ where E: Element<Impl=Impl, AttrString=String> + Clone + MatchAttrGeneric {
+ self.state_deps.compute_hint(element, snapshot, current_state)
+ }
+}
+
+
/// Map that contains the CSS rules for a given origin.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
struct PerOriginSelectorMap<Impl: SelectorImpl> {
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index d2acbc92d13..4907cc20629 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -1068,7 +1068,7 @@ 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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1796,7 +1796,7 @@ 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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1832,7 +1832,7 @@ dependencies = [
"profile_traits 0.0.1",
"range 0.0.1",
"script_traits 0.0.1",
- "selectors 0.6.0 (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)",
"style 0.0.1",
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1870,7 +1870,7 @@ dependencies = [
[[package]]
name = "selectors"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2128,7 +2128,7 @@ dependencies = [
"num-traits 0.1.32 (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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock
index 3fe70abd1d9..27b841fb790 100644
--- a/ports/geckolib/Cargo.lock
+++ b/ports/geckolib/Cargo.lock
@@ -12,7 +12,7 @@ dependencies = [
"libc 0.2.11 (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.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "selectors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
@@ -379,7 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "selectors"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -465,7 +465,7 @@ dependencies = [
"num-traits 0.1.32 (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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml
index 6ca0d6d4e2e..8f1112ccddc 100644
--- a/ports/geckolib/Cargo.toml
+++ b/ports/geckolib/Cargo.toml
@@ -37,7 +37,7 @@ lazy_static = "0.2"
libc = "0.2"
log = {version = "0.3.5", features = ["release_max_level_info"]}
num_cpus = "0.2.2"
-selectors = "0.6"
+selectors = "0.7"
smallvec = "0.1"
string_cache = {version = "0.2.20", features = ["unstable"]}
style = {path = "../../components/style", features = ["gecko"]}
diff --git a/ports/geckolib/data.rs b/ports/geckolib/data.rs
index 1962243a310..02fdece2411 100644
--- a/ports/geckolib/data.rs
+++ b/ports/geckolib/data.rs
@@ -9,6 +9,7 @@ use num_cpus;
use selector_impl::{Animation, SharedStyleContext, Stylist, Stylesheet};
use std::cmp;
use std::collections::HashMap;
+use std::env;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, RwLock};
use style::dom::OpaqueNode;
@@ -36,6 +37,17 @@ pub struct PerDocumentStyleData {
// FIXME(bholley): This shouldn't be per-document.
pub work_queue: WorkQueue<SharedStyleContext, WorkQueueData>,
+
+ pub num_threads: usize,
+}
+
+lazy_static! {
+ pub static ref NUM_THREADS: usize = {
+ match env::var("STYLO_THREADS").map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS")) {
+ Ok(num) => num,
+ _ => cmp::max(num_cpus::get() * 3 / 4, 1),
+ }
+ };
}
impl PerDocumentStyleData {
@@ -45,7 +57,6 @@ impl PerDocumentStyleData {
let device = Device::new(MediaType::Screen, window_size);
let (new_anims_sender, new_anims_receiver) = channel();
- let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
PerDocumentStyleData {
stylist: Arc::new(Stylist::new(device)),
@@ -55,7 +66,8 @@ impl PerDocumentStyleData {
new_animations_receiver: new_anims_receiver,
running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())),
- work_queue: WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads),
+ work_queue: WorkQueue::new("StyleWorker", thread_state::LAYOUT, *NUM_THREADS),
+ num_threads: *NUM_THREADS,
}
}
diff --git a/ports/geckolib/gecko_bindings/bindings.rs b/ports/geckolib/gecko_bindings/bindings.rs
index 6edc03d88ff..5014e701cf4 100644
--- a/ports/geckolib/gecko_bindings/bindings.rs
+++ b/ports/geckolib/gecko_bindings/bindings.rs
@@ -169,6 +169,25 @@ extern "C" {
pub fn Gecko_LocalName(element: *mut RawGeckoElement) -> *mut nsIAtom;
pub fn Gecko_Namespace(element: *mut RawGeckoElement) -> *mut nsIAtom;
pub fn Gecko_GetElementId(element: *mut RawGeckoElement) -> *mut nsIAtom;
+ pub fn Gecko_HasAttr(element: *mut RawGeckoElement, ns: *mut nsIAtom,
+ name: *mut nsIAtom) -> bool;
+ pub fn Gecko_AttrEquals(element: *mut RawGeckoElement, ns: *mut nsIAtom,
+ name: *mut nsIAtom, str: *mut nsIAtom,
+ ignoreCase: bool) -> bool;
+ pub fn Gecko_AttrDashEquals(element: *mut RawGeckoElement,
+ ns: *mut nsIAtom, name: *mut nsIAtom,
+ str: *mut nsIAtom) -> bool;
+ pub fn Gecko_AttrIncludes(element: *mut RawGeckoElement, ns: *mut nsIAtom,
+ name: *mut nsIAtom, str: *mut nsIAtom) -> bool;
+ pub fn Gecko_AttrHasSubstring(element: *mut RawGeckoElement,
+ ns: *mut nsIAtom, name: *mut nsIAtom,
+ str: *mut nsIAtom) -> bool;
+ pub fn Gecko_AttrHasPrefix(element: *mut RawGeckoElement,
+ ns: *mut nsIAtom, name: *mut nsIAtom,
+ str: *mut nsIAtom) -> bool;
+ pub fn Gecko_AttrHasSuffix(element: *mut RawGeckoElement,
+ ns: *mut nsIAtom, name: *mut nsIAtom,
+ str: *mut nsIAtom) -> bool;
pub fn Gecko_ClassOrClassList(element: *mut RawGeckoElement,
class_: *mut *mut nsIAtom,
classList: *mut *mut *mut nsIAtom) -> u32;
@@ -182,7 +201,6 @@ extern "C" {
-> *mut nsIAtom;
pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
pub fn Gecko_ReleaseAtom(aAtom: *mut nsIAtom);
- pub fn Gecko_HashAtom(aAtom: *mut nsIAtom) -> u32;
pub fn Gecko_GetAtomAsUTF16(aAtom: *mut nsIAtom, aLength: *mut u32)
-> *const u16;
pub fn Gecko_AtomEqualsUTF8(aAtom: *mut nsIAtom,
@@ -209,9 +227,6 @@ extern "C" {
pub fn Gecko_CreateGradient(shape: u8, size: u8, repeating: bool,
legacy_syntax: bool, stops: u32)
-> *mut nsStyleGradient;
- pub fn Gecko_SetGradientStop(gradient: *mut nsStyleGradient, index: u32,
- location: *const nsStyleCoord,
- color: nscolor, is_interpolation_hint: bool);
pub fn Gecko_AddRefPrincipalArbitraryThread(aPtr:
*mut ThreadSafePrincipalHolder);
pub fn Gecko_ReleasePrincipalArbitraryThread(aPtr:
@@ -282,6 +297,7 @@ extern "C" {
set: *mut RawServoStyleSet);
pub fn Servo_RestyleSubtree(node: *mut RawGeckoNode,
set: *mut RawServoStyleSet);
+ pub fn Servo_StyleWorkerThreadCount() -> u32;
pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement,
ns: *mut nsIAtom, name: *mut nsIAtom,
length: *mut u32)
diff --git a/ports/geckolib/gecko_bindings/structs_debug.rs b/ports/geckolib/gecko_bindings/structs_debug.rs
index 4a21baf0a99..b08a42d5084 100644
--- a/ports/geckolib/gecko_bindings/structs_debug.rs
+++ b/ports/geckolib/gecko_bindings/structs_debug.rs
@@ -188,8 +188,6 @@ pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69;
pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1;
pub const NSID_LENGTH: ::std::os::raw::c_uint = 39;
pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2;
-pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1;
-pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1;
pub const TWIPS_PER_POINT_INT: ::std::os::raw::c_uint = 20;
pub const POINTS_PER_INCH_INT: ::std::os::raw::c_uint = 72;
pub const NS_FONT_VARIANT_NORMAL: ::std::os::raw::c_uint = 0;
@@ -2903,6 +2901,16 @@ pub struct pair<_T1, _T2> {
pub first: _T1,
pub second: _T2,
}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct __make_pair_return_impl<_Tp> {
+ pub _phantom0: ::std::marker::PhantomData<_Tp>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct __make_pair_return<_Tp> {
+ pub _phantom0: ::std::marker::PhantomData<_Tp>,
+}
pub type Float = f32;
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -2931,12 +2939,17 @@ pub enum SurfaceFormat {
R8G8B8X8 = 3,
A8R8G8B8 = 4,
X8R8G8B8 = 5,
- R5G6B5_UINT16 = 6,
- A8 = 7,
- YUV = 8,
- NV12 = 9,
- YUV422 = 10,
- UNKNOWN = 11,
+ R8G8B8 = 6,
+ B8G8R8 = 7,
+ R5G6B5_UINT16 = 8,
+ A8 = 9,
+ YUV = 10,
+ NV12 = 11,
+ YUV422 = 12,
+ HSV = 13,
+ Lab = 14,
+ Depth = 15,
+ UNKNOWN = 16,
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -3072,7 +3085,7 @@ pub enum FillRule { FILL_WINDING = 0, FILL_EVEN_ODD = 1, }
pub enum AntialiasMode { NONE = 0, GRAY = 1, SUBPIXEL = 2, DEFAULT = 3, }
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Filter { GOOD = 0, LINEAR = 1, POINT = 2, SENTINEL = 3, }
+pub enum SamplingFilter { GOOD = 0, LINEAR = 1, POINT = 2, SENTINEL = 3, }
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum PatternType {
@@ -3159,16 +3172,6 @@ pub enum SideBits {
eSideBitsLeftRight = 10,
eSideBitsAll = 15,
}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct tuple_size<_Tp> {
- pub _phantom0: ::std::marker::PhantomData<_Tp>,
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct tuple_element<_Tp> {
- pub _phantom0: ::std::marker::PhantomData<_Tp>,
-}
pub type nscoord = i32;
#[repr(C)]
pub struct nsIntPoint {
@@ -3269,7 +3272,7 @@ pub const eFamily_generic_count: FontFamilyType =
* generic (e.g. serif, sans-serif), with the ability to distinguish
* between unquoted and quoted names for serializaiton
*/
-#[repr(u32)]
+#[repr(i32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum FontFamilyType {
eFamily_none = 0,
@@ -3389,7 +3392,7 @@ fn bindgen_test_layout_nsFont() {
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum StyleBoxSizing { Content = 0, Padding = 1, Border = 2, }
+pub enum StyleBoxSizing { Content = 0, Border = 1, }
#[repr(i32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum PlaybackDirection { _BindgenOpaqueEnum = 0, }
@@ -5069,6 +5072,9 @@ pub enum nsStyleImageLayers_nsStyleStruct_h_unnamed_19 {
maskMode = 10,
composite = 11,
}
+#[repr(i8)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum nsStyleImageLayers_LayerType { Background = 0, Mask = 1, }
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsStyleImageLayers_Position {
@@ -5645,8 +5651,8 @@ pub struct nsStyleDisplay {
pub mContain: u8,
pub mAppearance: u8,
pub mPosition: u8,
- pub mFloats: u8,
- pub mOriginalFloats: u8,
+ pub mFloat: u8,
+ pub mOriginalFloat: u8,
pub mBreakType: u8,
pub mBreakInside: u8,
pub mBreakBefore: bool,
diff --git a/ports/geckolib/gecko_bindings/structs_release.rs b/ports/geckolib/gecko_bindings/structs_release.rs
index 457f8c17295..c7559d71b43 100644
--- a/ports/geckolib/gecko_bindings/structs_release.rs
+++ b/ports/geckolib/gecko_bindings/structs_release.rs
@@ -188,8 +188,6 @@ pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69;
pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1;
pub const NSID_LENGTH: ::std::os::raw::c_uint = 39;
pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2;
-pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1;
-pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1;
pub const TWIPS_PER_POINT_INT: ::std::os::raw::c_uint = 20;
pub const POINTS_PER_INCH_INT: ::std::os::raw::c_uint = 72;
pub const NS_FONT_VARIANT_NORMAL: ::std::os::raw::c_uint = 0;
@@ -2882,6 +2880,16 @@ pub struct pair<_T1, _T2> {
pub first: _T1,
pub second: _T2,
}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct __make_pair_return_impl<_Tp> {
+ pub _phantom0: ::std::marker::PhantomData<_Tp>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct __make_pair_return<_Tp> {
+ pub _phantom0: ::std::marker::PhantomData<_Tp>,
+}
pub type Float = f32;
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -2910,12 +2918,17 @@ pub enum SurfaceFormat {
R8G8B8X8 = 3,
A8R8G8B8 = 4,
X8R8G8B8 = 5,
- R5G6B5_UINT16 = 6,
- A8 = 7,
- YUV = 8,
- NV12 = 9,
- YUV422 = 10,
- UNKNOWN = 11,
+ R8G8B8 = 6,
+ B8G8R8 = 7,
+ R5G6B5_UINT16 = 8,
+ A8 = 9,
+ YUV = 10,
+ NV12 = 11,
+ YUV422 = 12,
+ HSV = 13,
+ Lab = 14,
+ Depth = 15,
+ UNKNOWN = 16,
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -3051,7 +3064,7 @@ pub enum FillRule { FILL_WINDING = 0, FILL_EVEN_ODD = 1, }
pub enum AntialiasMode { NONE = 0, GRAY = 1, SUBPIXEL = 2, DEFAULT = 3, }
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Filter { GOOD = 0, LINEAR = 1, POINT = 2, SENTINEL = 3, }
+pub enum SamplingFilter { GOOD = 0, LINEAR = 1, POINT = 2, SENTINEL = 3, }
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum PatternType {
@@ -3138,16 +3151,6 @@ pub enum SideBits {
eSideBitsLeftRight = 10,
eSideBitsAll = 15,
}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct tuple_size<_Tp> {
- pub _phantom0: ::std::marker::PhantomData<_Tp>,
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct tuple_element<_Tp> {
- pub _phantom0: ::std::marker::PhantomData<_Tp>,
-}
pub type nscoord = i32;
#[repr(C)]
pub struct nsIntPoint {
@@ -3248,7 +3251,7 @@ pub const eFamily_generic_count: FontFamilyType =
* generic (e.g. serif, sans-serif), with the ability to distinguish
* between unquoted and quoted names for serializaiton
*/
-#[repr(u32)]
+#[repr(i32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum FontFamilyType {
eFamily_none = 0,
@@ -3368,7 +3371,7 @@ fn bindgen_test_layout_nsFont() {
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum StyleBoxSizing { Content = 0, Padding = 1, Border = 2, }
+pub enum StyleBoxSizing { Content = 0, Border = 1, }
#[repr(i32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum PlaybackDirection { _BindgenOpaqueEnum = 0, }
@@ -5047,6 +5050,9 @@ pub enum nsStyleImageLayers_nsStyleStruct_h_unnamed_19 {
maskMode = 10,
composite = 11,
}
+#[repr(i8)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum nsStyleImageLayers_LayerType { Background = 0, Mask = 1, }
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsStyleImageLayers_Position {
@@ -5623,8 +5629,8 @@ pub struct nsStyleDisplay {
pub mContain: u8,
pub mAppearance: u8,
pub mPosition: u8,
- pub mFloats: u8,
- pub mOriginalFloats: u8,
+ pub mFloat: u8,
+ pub mOriginalFloat: u8,
pub mBreakType: u8,
pub mBreakInside: u8,
pub mBreakBefore: bool,
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index 8f76407749c..f1650be83f6 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -5,7 +5,7 @@
#![allow(unsafe_code)]
use app_units::Au;
-use data::PerDocumentStyleData;
+use data::{NUM_THREADS, PerDocumentStyleData};
use env_logger;
use euclid::Size2D;
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
@@ -29,6 +29,7 @@ use style::parallel;
use style::parser::ParserContextExtraData;
use style::properties::{ComputedValues, PropertyDeclarationBlock};
use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType};
+use style::sequential;
use style::stylesheets::Origin;
use traversal::RecalcStyleOnly;
use url::Url;
@@ -109,7 +110,12 @@ fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) {
};
if node.is_dirty() || node.has_dirty_descendants() {
- parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut per_doc_data.work_queue);
+ if per_doc_data.num_threads == 1 {
+ sequential::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context);
+ } else {
+ parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context,
+ &mut per_doc_data.work_queue);
+ }
}
}
@@ -131,6 +137,11 @@ pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument, raw_data: *m
}
#[no_mangle]
+pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
+ *NUM_THREADS as u32
+}
+
+#[no_mangle]
pub extern "C" fn Servo_DropNodeData(data: *mut ServoNodeData) -> () {
unsafe {
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs
index c3c90da9cb3..357cb9a3d70 100644
--- a/ports/geckolib/lib.rs
+++ b/ports/geckolib/lib.rs
@@ -39,3 +39,7 @@ mod wrapper;
pub mod properties {
include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}
+
+// FIXME(bholley): This should probably go away once we harmonize the allocators.
+#[no_mangle]
+pub extern "C" fn je_malloc_usable_size(_: *const ::libc::c_void) -> ::libc::size_t { 0 }
diff --git a/ports/geckolib/selector_impl.rs b/ports/geckolib/selector_impl.rs
index c1284015414..a2f0d1eba92 100644
--- a/ports/geckolib/selector_impl.rs
+++ b/ports/geckolib/selector_impl.rs
@@ -4,6 +4,7 @@
use properties::GeckoComputedValues;
use selectors::parser::{ParserContext, SelectorImpl};
+use string_cache::Atom;
use style;
use style::element_state::ElementState;
use style::selector_impl::{PseudoElementCascadeType, SelectorImplExt};
@@ -157,6 +158,7 @@ impl NonTSPseudoClass {
}
impl SelectorImpl for GeckoSelectorImpl {
+ type AttrString = Atom;
type PseudoElement = PseudoElement;
type NonTSPseudoClass = NonTSPseudoClass;
fn parse_non_ts_pseudo_class(_context: &ParserContext,
diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs
index 2c32643c008..29f3ee99900 100644
--- a/ports/geckolib/wrapper.rs
+++ b/ports/geckolib/wrapper.rs
@@ -4,6 +4,7 @@
#![allow(unsafe_code)]
+use gecko_bindings::bindings;
use gecko_bindings::bindings::Gecko_ChildrenCount;
use gecko_bindings::bindings::Gecko_ClassOrClassList;
use gecko_bindings::bindings::Gecko_GetElementId;
@@ -361,18 +362,23 @@ impl<'le> TElement for GeckoElement<'le> {
}
#[inline]
- fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
+ fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool {
unsafe {
- let mut length: u32 = 0;
- let ptr = Gecko_GetAttrAsUTF8(self.element, namespace.0.as_ptr(), name.as_ptr(),
- &mut length);
- reinterpret_string(ptr, length)
+ bindings::Gecko_HasAttr(self.element,
+ namespace.0.as_ptr(),
+ attr.as_ptr())
}
}
#[inline]
- fn get_attrs<'a>(&'a self, _name: &Atom) -> Vec<&'a str> {
- unimplemented!()
+ fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool {
+ unsafe {
+ bindings::Gecko_AttrEquals(self.element,
+ namespace.0.as_ptr(),
+ attr.as_ptr(),
+ val.as_ptr(),
+ /* ignoreCase = */ false)
+ }
}
}
@@ -506,27 +512,101 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
}
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
- // FIXME(bholley): This is copy-pasted from the servo wrapper's version.
- // We should find a way to share it.
- let name = if self.is_html_element_in_html_document() {
- &attr.lower_name
+ fn is_html_element_in_html_document(&self) -> bool {
+ unsafe {
+ Gecko_IsHTMLElementInHTMLDocument(self.element)
+ }
+ }
+}
+
+trait AttrSelectorHelpers {
+ fn ns_or_null(&self) -> *mut nsIAtom;
+ fn select_name<'le>(&self, el: &GeckoElement<'le>) -> *mut nsIAtom;
+}
+
+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(),
+ }
+ }
+
+ fn select_name<'le>(&self, el: &GeckoElement<'le>) -> *mut nsIAtom {
+ if el.is_html_element_in_html_document() {
+ self.lower_name.as_ptr()
} else {
- &attr.name
- };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attr(ns, name).map_or(false, |attr| test(attr))
- },
- NamespaceConstraint::Any => {
- self.get_attrs(name).iter().any(|attr| test(*attr))
- }
+ self.name.as_ptr()
}
+
}
+}
- fn is_html_element_in_html_document(&self) -> bool {
+impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
+ type AttrString = Atom;
+ fn match_attr_has(&self, attr: &AttrSelector) -> bool {
unsafe {
- Gecko_IsHTMLElementInHTMLDocument(self.element)
+ bindings::Gecko_HasAttr(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self))
+ }
+ }
+ fn match_attr_equals(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrEquals(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr(),
+ /* ignoreCase = */ false)
+ }
+ }
+ fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrEquals(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr(),
+ /* ignoreCase = */ false)
+ }
+ }
+ fn match_attr_includes(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrIncludes(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr())
+ }
+ }
+ fn match_attr_dash(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrDashEquals(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr())
+ }
+ }
+ fn match_attr_prefix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrHasPrefix(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr())
+ }
+ }
+ fn match_attr_substring(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrHasSubstring(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr())
+ }
+ }
+ fn match_attr_suffix(&self, attr: &AttrSelector, value: &Self::AttrString) -> bool {
+ unsafe {
+ bindings::Gecko_AttrHasSuffix(self.element,
+ attr.ns_or_null(),
+ attr.select_name(self),
+ value.as_ptr())
}
}
}
diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml
index 1e8e120651f..8063e1a5b8d 100644
--- a/tests/unit/style/Cargo.toml
+++ b/tests/unit/style/Cargo.toml
@@ -13,7 +13,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.6", features = ["heap_size"]}
+selectors = {version = "0.7", features = ["heap_size"]}
string_cache = {version = "0.2", features = ["heap_size"]}
style = {path = "../../../components/style"}
style_traits = {path = "../../../components/style_traits"}