servo: Merge #13110 - Fix incremental restyling under some circumstances due to our bogus use of ElementFlags (from emilio:element-flags); r=SimonSapin
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Thu, 01 Sep 2016 02:44:36 -0500
changeset 339628 ced862e8d715d12d50c2cbc97bd78300e15e880c
parent 339627 42502fab98dda5e7d6a281115367deb47b35894a
child 339629 d730fe3fd84ecee8e3e677cf5a60cd176bc38e65
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersSimonSapin
servo: Merge #13110 - Fix incremental restyling under some circumstances due to our bogus use of ElementFlags (from emilio:element-flags); r=SimonSapin <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] There are tests for these changes OR <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Depends on https://github.com/servo/rust-selectors/pull/98 Source-Repo: https://github.com/servo/servo Source-Revision: 57b372ba3bfc8c1c99c541be8d68fac93deb41ca
servo/components/layout/Cargo.toml
servo/components/script/Cargo.toml
servo/components/script/dom/element.rs
servo/components/script/dom/node.rs
servo/components/script_layout_interface/Cargo.toml
servo/components/servo/Cargo.lock
servo/components/style/Cargo.toml
servo/components/style/matching.rs
servo/components/style/restyle_hints.rs
servo/components/style/selector_matching.rs
servo/ports/cef/Cargo.lock
servo/ports/geckolib/Cargo.lock
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/string_cache/Cargo.toml
servo/tests/unit/style/Cargo.toml
--- a/servo/components/layout/Cargo.toml
+++ b/servo/components/layout/Cargo.toml
@@ -28,17 +28,17 @@ msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 ordered-float = "0.2.2"
 plugins = {path = "../plugins"}
 profile_traits = {path = "../profile_traits"}
 range = {path = "../range"}
 rustc-serialize = "0.3"
 script_layout_interface = {path = "../script_layout_interface"}
 script_traits = {path = "../script_traits"}
-selectors = {version = "0.12", features = ["heap_size"]}
+selectors = {version = "0.13", features = ["heap_size"]}
 serde_macros = "0.8"
 smallvec = "0.1"
 string_cache = {version = "0.2.26", features = ["heap_size"]}
 style = {path = "../style"}
 style_traits = {path = "../style_traits"}
 unicode-bidi = "0.2"
 unicode-script = {version = "0.1", features = ["harfbuzz"]}
 url = {version = "1.2", features = ["heap_size"]}
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -56,17 +56,17 @@ plugins = {path = "../plugins"}
 profile_traits = {path = "../profile_traits"}
 rand = "0.3"
 range = {path = "../range"}
 ref_slice = "1.0"
 regex = "0.1.43"
 rustc-serialize = "0.3"
 script_layout_interface = {path = "../script_layout_interface"}
 script_traits = {path = "../script_traits"}
-selectors = {version = "0.12", features = ["heap_size"]}
+selectors = {version = "0.13", features = ["heap_size"]}
 serde = "0.8"
 smallvec = "0.1"
 string_cache = {version = "0.2.26", features = ["heap_size", "unstable"]}
 style = {path = "../style"}
 time = "0.1.12"
 url = {version = "1.2", features = ["heap_size", "query_encoding"]}
 util = {path = "../util"}
 uuid = {version = "0.3.1", features = ["v4"]}
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -65,17 +65,17 @@ use dom::nodelist::NodeList;
 use dom::text::Text;
 use dom::validation::Validatable;
 use dom::virtualmethods::{VirtualMethods, vtable_for};
 use html5ever::serialize;
 use html5ever::serialize::SerializeOpts;
 use html5ever::serialize::TraversalScope;
 use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
 use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks};
-use selectors::matching::{ElementFlags, matches};
+use selectors::matching::{ElementFlags, MatchingReason, matches};
 use selectors::matching::{HAS_SLOW_SELECTOR, HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
 use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str};
 use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::convert::TryFrom;
 use std::default::Default;
 use std::fmt;
@@ -2001,17 +2001,17 @@ impl ElementMethods for Element {
         self.upcast::<Node>().remove_self();
     }
 
     // https://dom.spec.whatwg.org/#dom-element-matches
     fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
         match parse_author_origin_selector_list_from_str(&selectors) {
             Err(()) => Err(Error::Syntax),
             Ok(ref selectors) => {
-                Ok(matches(selectors, &Root::from_ref(self), None))
+                Ok(matches(selectors, &Root::from_ref(self), None, MatchingReason::Other))
             }
         }
     }
 
     // https://dom.spec.whatwg.org/#dom-element-webkitmatchesselector
     fn WebkitMatchesSelector(&self, selectors: DOMString) -> Fallible<bool> {
         self.Matches(selectors)
     }
@@ -2019,17 +2019,17 @@ impl ElementMethods for Element {
     // https://dom.spec.whatwg.org/#dom-element-closest
     fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
         match parse_author_origin_selector_list_from_str(&selectors) {
             Err(()) => Err(Error::Syntax),
             Ok(ref selectors) => {
                 let root = self.upcast::<Node>();
                 for element in root.inclusive_ancestors() {
                     if let Some(element) = Root::downcast::<Element>(element) {
-                        if matches(selectors, &element, None) {
+                        if matches(selectors, &element, None, MatchingReason::Other) {
                             return Ok(Some(element));
                         }
                     }
                 }
                 Ok(None)
             }
         }
     }
--- a/servo/components/script/dom/node.rs
+++ b/servo/components/script/dom/node.rs
@@ -58,17 +58,17 @@ use js::jsapi::{JSContext, JSObject, JSR
 use libc::{self, c_void, uintptr_t};
 use msg::constellation_msg::PipelineId;
 use parse::html::parse_html_fragment;
 use ref_slice::ref_slice;
 use script_layout_interface::message::Msg;
 use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData};
 use script_layout_interface::{LayoutNodeType, LayoutElementType, TrustedNodeAddress};
 use script_traits::UntrustedNodeAddress;
-use selectors::matching::matches;
+use selectors::matching::{MatchingReason, matches};
 use selectors::parser::Selector;
 use selectors::parser::parse_author_origin_selector_list_from_str;
 use std::borrow::ToOwned;
 use std::cell::{Cell, UnsafeCell};
 use std::cmp::max;
 use std::default::Default;
 use std::iter;
 use std::mem;
@@ -314,17 +314,17 @@ impl<'a> Iterator for QuerySelectorItera
     type Item = Root<Node>;
 
     fn next(&mut self) -> Option<Root<Node>> {
         let selectors = &self.selectors;
         // TODO(cgaebel): Is it worth it to build a bloom filter here
         // (instead of passing `None`)? Probably.
         self.iterator.by_ref().filter_map(|node| {
             if let Some(element) = Root::downcast(node) {
-                if matches(selectors, &element, None) {
+                if matches(selectors, &element, None, MatchingReason::Other) {
                     return Some(Root::upcast(element));
                 }
             }
             None
         }).next()
     }
 }
 
@@ -706,17 +706,17 @@ impl Node {
     pub fn query_selector(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
         // Step 1.
         match parse_author_origin_selector_list_from_str(&selectors) {
             // Step 2.
             Err(()) => Err(Error::Syntax),
             // Step 3.
             Ok(ref selectors) => {
                 Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| {
-                    matches(selectors, element, None)
+                    matches(selectors, element, None, MatchingReason::Other)
                 }))
             }
         }
     }
 
     /// https://dom.spec.whatwg.org/#scope-match-a-selectors-string
     /// Get an iterator over all nodes which match a set of selectors
     /// Be careful not to do anything which may manipulate the DOM tree
--- a/servo/components/script_layout_interface/Cargo.toml
+++ b/servo/components/script_layout_interface/Cargo.toml
@@ -22,13 +22,13 @@ ipc-channel = "0.5"
 libc = "0.2"
 log = "0.3.5"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 plugins = {path = "../plugins"}
 profile_traits = {path = "../profile_traits"}
 range = {path = "../range"}
 script_traits = {path = "../script_traits"}
-selectors = {version = "0.12", features = ["heap_size"]}
+selectors = {version = "0.13", features = ["heap_size"]}
 string_cache = {version = "0.2.26", features = ["heap_size"]}
 style = {path = "../style"}
 url = {version = "1.2", features = ["heap_size"]}
 util = {path = "../util"}
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -1159,17 +1159,17 @@ dependencies = [
  "net_traits 0.0.1",
  "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "profile_traits 0.0.1",
  "range 0.0.1",
  "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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.3 (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.26 (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)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1924,17 +1924,17 @@ dependencies = [
  "profile_traits 0.0.1",
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
  "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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.3 (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.26 (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)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
@@ -1960,17 +1960,17 @@ dependencies = [
  "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "plugins 0.0.1",
  "profile_traits 0.0.1",
  "range 0.0.1",
  "script_traits 0.0.1",
- "selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
 [[package]]
 name = "script_tests"
@@ -2009,17 +2009,17 @@ dependencies = [
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
 [[package]]
 name = "selectors"
-version = "0.12.0"
+version = "0.13.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)",
  "cssparser 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2231,17 +2231,17 @@ dependencies = [
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "quickersort 2.1.0 (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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.3 (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.26 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
@@ -2251,17 +2251,17 @@ dependencies = [
 [[package]]
 name = "style_tests"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
 [[package]]
@@ -2862,17 +2862,17 @@ dependencies = [
 "checksum rayon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e501871917624668fe601ad12a730450414f9b0b64722a898b040ce3ae1b0fa"
 "checksum ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24c91f8f8903c37f0525112df98ef53b1985abca5702972e5e00854cd874baf2"
 "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
 "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
 "checksum rustc-demangle 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4c2d35b2ed94cec4fad26a36eee4d6eff394ce70a8ceea064b0b6ca42ea4cf0"
 "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a"
-"checksum selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd81c2af3eba55ccc7048696c517a0e594ae9a4045b8fb3cc6ad80cd6d65ca5"
+"checksum selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9eee17ca1807581fc4cf0bfddda311dc421f295a71314b9276ecc787cc63ed6f"
 "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
 "checksum serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bfdad8985ce7708e21ada7f3f188a0079de4f8e239155348a024e31f13cddf86"
 "checksum serde_codegen 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5ae9f0068a5f3266ac4d69eb0c1f9f048a2ac24a42af3db567bcd9a3ffe9d47e"
 "checksum serde_codegen_internals 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0f26cea4f76805a062c641ca0c48ddaf0ee45e5f080ed22c48bc3162253b1c0"
 "checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc"
 "checksum serde_macros 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f520f1b4742011632108aa62397173788e14f819d3694e863b1a981c80f1ec47"
 "checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217"
 "checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -35,17 +35,17 @@ lazy_static = "0.2"
 log = "0.3.5"
 matches = "0.1"
 num-integer = "0.1.32"
 num-traits = "0.1.32"
 ordered-float = "0.2.2"
 quickersort = "2.0.0"
 rand = "0.3"
 rustc-serialize = "0.3"
-selectors = "0.12"
+selectors = "0.13"
 serde = {version = "0.8", optional = true}
 serde_macros = {version = "0.8", optional = true}
 smallvec = "0.1"
 string_cache = {version = "0.2.26", features = ["heap_size"], optional = true}
 style_traits = {path = "../style_traits"}
 time = "0.1"
 url = "1.2"
 util = {path = "../util"}
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -13,17 +13,17 @@ use cascade_info::CascadeInfo;
 use context::{StyleContext, SharedStyleContext};
 use data::PrivateStyleData;
 use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
 use properties::longhands::display::computed_value as display;
 use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
 use selector_impl::{TheSelectorImpl, PseudoElement};
 use selector_matching::{DeclarationBlock, Stylist};
 use selectors::bloom::BloomFilter;
-use selectors::matching::{StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS};
+use selectors::matching::{MatchingReason, StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS};
 use selectors::{Element, MatchAttr};
 use sink::ForgetfulSink;
 use smallvec::SmallVec;
 use std::collections::HashMap;
 use std::hash::{BuildHasherDefault, Hash, Hasher};
 use std::slice::IterMut;
 use std::sync::Arc;
 use string_cache::Atom;
@@ -653,26 +653,28 @@ pub trait ElementMatchMethods : TElement
         use traversal::relations_are_shareable;
         let style_attribute = self.style_attribute();
 
         let mut relations =
             stylist.push_applicable_declarations(self,
                                                  parent_bf,
                                                  style_attribute,
                                                  None,
-                                                 &mut applicable_declarations.normal);
+                                                 &mut applicable_declarations.normal,
+                                                 MatchingReason::ForStyling);
 
         applicable_declarations.normal_shareable = relations_are_shareable(&relations);
 
         TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
             stylist.push_applicable_declarations(self,
                                                  parent_bf,
                                                  None,
                                                  Some(&pseudo.clone()),
-                                                 applicable_declarations.per_pseudo.entry(pseudo).or_insert(vec![]));
+                                                 applicable_declarations.per_pseudo.entry(pseudo).or_insert(vec![]),
+                                                 MatchingReason::ForStyling);
         });
 
         let has_pseudos =
             applicable_declarations.per_pseudo.values().any(|v| !v.is_empty());
 
         if has_pseudos {
             relations |= AFFECTED_BY_PSEUDO_ELEMENTS;
         }
--- a/servo/components/style/restyle_hints.rs
+++ b/servo/components/style/restyle_hints.rs
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Restyle hints: an optimization to avoid unnecessarily matching selectors.
 
 use element_state::*;
 #[cfg(feature = "servo")]
 use heapsize::HeapSizeOf;
 use selector_impl::{ElementExt, TheSelectorImpl, NonTSPseudoClass, AttrValue};
-use selectors::matching::StyleRelations;
 use selectors::matching::matches_complex_selector;
+use selectors::matching::{MatchingReason, StyleRelations};
 use selectors::parser::{AttrSelector, Combinator, ComplexSelector, SimpleSelector, SelectorImpl};
 use selectors::{Element, MatchAttr};
 use std::clone::Clone;
 use std::sync::Arc;
 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
@@ -471,20 +471,22 @@ impl DependencySet {
         }
         for dep in deps {
             debug_assert!((!state_changes.is_empty() && !dep.sensitivities.states.is_empty()) ||
                           (attrs_changed && dep.sensitivities.attrs),
                           "Testing a known ineffective dependency?");
             if (attrs_changed || state_changes.intersects(dep.sensitivities.states)) && !hint.intersects(dep.hint) {
                 let matched_then =
                     matches_complex_selector(&dep.selector, snapshot, None,
-                                             &mut StyleRelations::empty());
+                                             &mut StyleRelations::empty(),
+                                             MatchingReason::Other);
                 let matches_now =
                     matches_complex_selector(&dep.selector, element, None,
-                                             &mut StyleRelations::empty());
+                                             &mut StyleRelations::empty(),
+                                             MatchingReason::Other);
                 if matched_then != matches_now {
                     hint.insert(dep.hint);
                 }
                 if hint.is_all() {
                     break;
                 }
             }
         }
--- a/servo/components/style/selector_matching.rs
+++ b/servo/components/style/selector_matching.rs
@@ -11,17 +11,17 @@ use keyframes::KeyframesAnimation;
 use media_queries::{Device, MediaType};
 use properties::{self, PropertyDeclaration, PropertyDeclarationBlock, ComputedValues, Importance};
 use quickersort::sort_by;
 use restyle_hints::{RestyleHint, DependencySet};
 use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement};
 use selectors::Element;
 use selectors::bloom::BloomFilter;
 use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS};
-use selectors::matching::{StyleRelations, matches_complex_selector};
+use selectors::matching::{MatchingReason, StyleRelations, matches_complex_selector};
 use selectors::parser::{Selector, SimpleSelector, LocalName, ComplexSelector};
 use sink::Push;
 use smallvec::VecLike;
 use std::borrow::Borrow;
 use std::collections::HashMap;
 use std::fmt;
 use std::hash::BuildHasherDefault;
 use std::hash::Hash;
@@ -288,17 +288,18 @@ impl Stylist {
         let mut declarations = vec![];
 
         // NB: This being cached could be worth it, maybe allow an optional
         // ApplicableDeclarationsCache?.
         self.push_applicable_declarations(element,
                                           None,
                                           None,
                                           Some(pseudo),
-                                          &mut declarations);
+                                          &mut declarations,
+                                          MatchingReason::ForStyling);
 
         let (computed, _) =
             properties::cascade(self.device.au_viewport_size(),
                                 &declarations, false,
                                 Some(&**parent), None, None,
                                 Box::new(StdoutErrorReporter));
 
 
@@ -339,17 +340,18 @@ impl Stylist {
     /// matching logic to be reduced to the logic in
     /// `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
     pub fn push_applicable_declarations<E, V>(
                                         &self,
                                         element: &E,
                                         parent_bf: Option<&BloomFilter>,
                                         style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
                                         pseudo_element: Option<&PseudoElement>,
-                                        applicable_declarations: &mut V) -> StyleRelations
+                                        applicable_declarations: &mut V,
+                                        reason: MatchingReason) -> StyleRelations
         where E: Element<Impl=TheSelectorImpl> +
                  fmt::Debug +
                  PresentationalHintsSynthetizer,
               V: Push<DeclarationBlock> + VecLike<DeclarationBlock>
     {
         assert!(!self.is_device_dirty);
         assert!(style_attribute.is_none() || pseudo_element.is_none(),
                 "Style attributes do not apply to pseudo-elements");
@@ -365,16 +367,17 @@ impl Stylist {
         let mut relations = StyleRelations::empty();
 
         debug!("Determining if style is shareable: pseudo: {}", pseudo_element.is_some());
         // Step 1: Normal user-agent rules.
         map.user_agent.normal.get_all_matching_rules(element,
                                                      parent_bf,
                                                      applicable_declarations,
                                                      &mut relations,
+                                                     reason,
                                                      Importance::Normal);
         debug!("UA normal: {:?}", relations);
 
         // Step 2: Presentational hints.
         let length = applicable_declarations.len();
         element.synthesize_presentational_hints_for_legacy_attributes(applicable_declarations);
         if applicable_declarations.len() != length {
             // Never share style for elements with preshints
@@ -382,22 +385,24 @@ impl Stylist {
         }
         debug!("preshints: {:?}", relations);
 
         // Step 3: User and author normal rules.
         map.user.normal.get_all_matching_rules(element,
                                                parent_bf,
                                                applicable_declarations,
                                                &mut relations,
+                                               reason,
                                                Importance::Normal);
         debug!("user normal: {:?}", relations);
         map.author.normal.get_all_matching_rules(element,
                                                  parent_bf,
                                                  applicable_declarations,
                                                  &mut relations,
+                                                 reason,
                                                  Importance::Normal);
         debug!("author normal: {:?}", relations);
 
         // Step 4: Normal style attributes.
         if let Some(sa)  = style_attribute {
             if sa.any_normal() {
                 relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
                 Push::push(
@@ -408,16 +413,17 @@ impl Stylist {
 
         debug!("style attr: {:?}", relations);
 
         // Step 5: Author-supplied `!important` rules.
         map.author.important.get_all_matching_rules(element,
                                                     parent_bf,
                                                     applicable_declarations,
                                                     &mut relations,
+                                                    reason,
                                                     Importance::Important);
 
         debug!("author important: {:?}", relations);
 
         // Step 6: `!important` style attributes.
         if let Some(sa) = style_attribute {
             if sa.any_important() {
                 relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
@@ -429,24 +435,26 @@ impl Stylist {
 
         debug!("style attr important: {:?}", relations);
 
         // Step 7: User and UA `!important` rules.
         map.user.important.get_all_matching_rules(element,
                                                   parent_bf,
                                                   applicable_declarations,
                                                   &mut relations,
+                                                  reason,
                                                   Importance::Important);
 
         debug!("user important: {:?}", relations);
 
         map.user_agent.important.get_all_matching_rules(element,
                                                         parent_bf,
                                                         applicable_declarations,
                                                         &mut relations,
+                                                        reason,
                                                         Importance::Important);
 
         debug!("UA important: {:?}", relations);
 
         debug!("push_applicable_declarations: shareable: {:?}", relations);
 
         relations
     }
@@ -463,59 +471,63 @@ impl Stylist {
 
     pub fn match_same_not_common_style_affecting_attributes_rules<E>(&self,
                                                                      element: &E,
                                                                      candidate: &E) -> bool
     where E: ElementExt
     {
         use selectors::matching::StyleRelations;
         use selectors::matching::matches_complex_selector;
-        // XXX we can probably do better, the candidate should already know what
-        // rules it matches.
+        // TODO(emilio): we can probably do better, the candidate should already
+        // know what rules it matches. Also, we should only match until we find
+        // a descendant combinator, the rest should be ok, since the parent is
+        // the same.
         //
-        // XXX Could the bloom filter help here? Should be available.
+        // TODO(emilio): Use the bloom filter, since they contain the element's
+        // ancestor chain and it's correct for the candidate too.
         for ref selector in self.non_common_style_affecting_attributes_selectors.iter() {
-            let element_matches = matches_complex_selector(&selector.complex_selector,
-                                                           element,
-                                                           None,
-                                                           &mut StyleRelations::empty());
-            let candidate_matches = matches_complex_selector(&selector.complex_selector,
-                                                             candidate,
-                                                             None,
-                                                             &mut StyleRelations::empty());
+            let element_matches =
+                matches_complex_selector(&selector.complex_selector, element,
+                                         None, &mut StyleRelations::empty(),
+                                         MatchingReason::Other);
+            let candidate_matches =
+                matches_complex_selector(&selector.complex_selector, candidate,
+                                         None, &mut StyleRelations::empty(),
+                                         MatchingReason::Other);
 
             if element_matches != candidate_matches {
                 return false;
             }
         }
 
         true
     }
 
     pub fn match_same_sibling_affecting_rules<E>(&self,
                                                  element: &E,
                                                  candidate: &E) -> bool
     where E: ElementExt
     {
         use selectors::matching::StyleRelations;
         use selectors::matching::matches_complex_selector;
-        // XXX we can probably do better, the candidate should already know what
-        // rules it matches.
+        // TODO(emilio): we can probably do better, the candidate should already
+        // know what rules it matches.
         //
-        // XXX The bloom filter would help here, and should be available.
+        // TODO(emilio): Use the bloom filter, since they contain the element's
+        // ancestor chain and it's correct for the candidate too.
         for ref selector in self.sibling_affecting_selectors.iter() {
-            let element_matches = matches_complex_selector(&selector.complex_selector,
-                                                           element,
-                                                           None,
-                                                           &mut StyleRelations::empty());
+            let element_matches =
+                matches_complex_selector(&selector.complex_selector, element,
+                                         None, &mut StyleRelations::empty(),
+                                         MatchingReason::Other);
 
-            let candidate_matches = matches_complex_selector(&selector.complex_selector,
-                                                             candidate,
-                                                             None,
-                                                             &mut StyleRelations::empty());
+            let candidate_matches =
+                matches_complex_selector(&selector.complex_selector, candidate,
+                                         None, &mut StyleRelations::empty(),
+                                         MatchingReason::Other);
 
             if element_matches != candidate_matches {
                 debug!("match_same_sibling_affecting_rules: Failure due to {:?}",
                        selector.complex_selector);
                 return false;
             }
         }
 
@@ -645,16 +657,17 @@ impl SelectorMap {
     ///
     /// Extract matching rules as per element's ID, classes, tag name, etc..
     /// Sort the Rules at the end to maintain cascading order.
     pub fn get_all_matching_rules<E, V>(&self,
                                         element: &E,
                                         parent_bf: Option<&BloomFilter>,
                                         matching_rules_list: &mut V,
                                         relations: &mut StyleRelations,
+                                        reason: MatchingReason,
                                         importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
               V: VecLike<DeclarationBlock>
     {
         if self.empty {
             return
         }
 
@@ -662,47 +675,51 @@ impl SelectorMap {
         let init_len = matching_rules_list.len();
         if let Some(id) = element.get_id() {
             SelectorMap::get_matching_rules_from_hash(element,
                                                       parent_bf,
                                                       &self.id_hash,
                                                       &id,
                                                       matching_rules_list,
                                                       relations,
+                                                      reason,
                                                       importance)
         }
 
         element.each_class(|class| {
             SelectorMap::get_matching_rules_from_hash(element,
                                                       parent_bf,
                                                       &self.class_hash,
                                                       class,
                                                       matching_rules_list,
                                                       relations,
+                                                      reason,
                                                       importance);
         });
 
         let local_name_hash = if element.is_html_element_in_html_document() {
             &self.lower_local_name_hash
         } else {
             &self.local_name_hash
         };
         SelectorMap::get_matching_rules_from_hash(element,
                                                   parent_bf,
                                                   local_name_hash,
                                                   element.get_local_name(),
                                                   matching_rules_list,
                                                   relations,
+                                                  reason,
                                                   importance);
 
         SelectorMap::get_matching_rules(element,
                                         parent_bf,
                                         &self.other_rules,
                                         matching_rules_list,
                                         relations,
+                                        reason,
                                         importance);
 
         // Sort only the rules we just added.
         sort_by_key(&mut matching_rules_list[init_len..],
                     |rule| (rule.specificity, rule.source_order));
     }
 
     /// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
@@ -730,52 +747,55 @@ impl SelectorMap {
 
     fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
         element: &E,
         parent_bf: Option<&BloomFilter>,
         hash: &FnvHashMap<Str, Vec<Rule>>,
         key: &BorrowedStr,
         matching_rules: &mut Vector,
         relations: &mut StyleRelations,
+        reason: MatchingReason,
         importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
               Str: Borrow<BorrowedStr> + Eq + Hash,
               BorrowedStr: Eq + Hash,
               Vector: VecLike<DeclarationBlock>
     {
         if let Some(rules) = hash.get(key) {
             SelectorMap::get_matching_rules(element,
                                             parent_bf,
                                             rules,
                                             matching_rules,
                                             relations,
+                                            reason,
                                             importance)
         }
     }
 
     /// Adds rules in `rules` that match `element` to the `matching_rules` list.
     fn get_matching_rules<E, V>(element: &E,
                                 parent_bf: Option<&BloomFilter>,
                                 rules: &[Rule],
                                 matching_rules: &mut V,
                                 relations: &mut StyleRelations,
+                                reason: MatchingReason,
                                 importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
               V: VecLike<DeclarationBlock>
     {
         for rule in rules.iter() {
             let block = &rule.declarations.mixed_declarations;
             let any_declaration_for_importance = if importance.important() {
                 block.any_important()
             } else {
                 block.any_normal()
             };
             if any_declaration_for_importance &&
-               matches_complex_selector(&*rule.selector,
-                                         element, parent_bf, relations) {
+               matches_complex_selector(&*rule.selector, element, parent_bf,
+                                        relations, reason) {
                 matching_rules.push(rule.declarations.clone());
             }
         }
     }
 
     /// Insert rule into the correct hash.
     /// Order in which to try: id_hash, class_hash, local_name_hash, other_rules.
     pub fn insert(&mut self, rule: Rule) {
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -1067,17 +1067,17 @@ dependencies = [
  "net_traits 0.0.1",
  "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "profile_traits 0.0.1",
  "range 0.0.1",
  "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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.3 (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.26 (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)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1776,17 +1776,17 @@ dependencies = [
  "profile_traits 0.0.1",
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
  "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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.3 (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.26 (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)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
@@ -1812,17 +1812,17 @@ dependencies = [
  "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "plugins 0.0.1",
  "profile_traits 0.0.1",
  "range 0.0.1",
  "script_traits 0.0.1",
- "selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
 [[package]]
 name = "script_traits"
@@ -1851,17 +1851,17 @@ dependencies = [
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
 [[package]]
 name = "selectors"
-version = "0.12.0"
+version = "0.13.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)",
  "cssparser 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2114,17 +2114,17 @@ dependencies = [
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "quickersort 2.1.0 (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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.3 (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.26 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
@@ -2716,17 +2716,17 @@ dependencies = [
 "checksum rayon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e501871917624668fe601ad12a730450414f9b0b64722a898b040ce3ae1b0fa"
 "checksum ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24c91f8f8903c37f0525112df98ef53b1985abca5702972e5e00854cd874baf2"
 "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
 "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
 "checksum rustc-demangle 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4c2d35b2ed94cec4fad26a36eee4d6eff394ce70a8ceea064b0b6ca42ea4cf0"
 "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a"
-"checksum selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd81c2af3eba55ccc7048696c517a0e594ae9a4045b8fb3cc6ad80cd6d65ca5"
+"checksum selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9eee17ca1807581fc4cf0bfddda311dc421f295a71314b9276ecc787cc63ed6f"
 "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
 "checksum serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bfdad8985ce7708e21ada7f3f188a0079de4f8e239155348a024e31f13cddf86"
 "checksum serde_codegen 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5ae9f0068a5f3266ac4d69eb0c1f9f048a2ac24a42af3db567bcd9a3ffe9d47e"
 "checksum serde_codegen_internals 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0f26cea4f76805a062c641ca0c48ddaf0ee45e5f080ed22c48bc3162253b1c0"
 "checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc"
 "checksum serde_macros 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f520f1b4742011632108aa62397173788e14f819d3694e863b1a981c80f1ec47"
 "checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217"
 "checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
--- a/servo/ports/geckolib/Cargo.lock
+++ b/servo/ports/geckolib/Cargo.lock
@@ -6,17 +6,17 @@ dependencies = [
  "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.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.15 (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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "aho-corasick"
 version = "0.5.2"
@@ -164,17 +164,17 @@ dependencies = [
 [[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.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "getopts"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -313,17 +313,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "rustc-serialize"
 version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "selectors"
-version = "0.12.0"
+version = "0.13.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)",
  "cssparser 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -369,17 +369,17 @@ dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quickersort 2.1.0 (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.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -533,17 +533,17 @@ source = "registry+https://github.com/ru
 "checksum ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cc511538298611a79d5a4ddfbb75315b866d942ed26a00bdc3590795c68b7279"
 "checksum phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)" = "04b5ea825e28cb6efd89d9133b129b2003b45a221aeda025509b125b00ecb7c4"
 "checksum phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2c43b5dbe94d31f1f4ed45c50bb06d70e72fd53f15422b0a915b5c237e130dd6"
 "checksum quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e952ea7699262481636004bc4ab8afaccf2bc13f91b79d1aee6617bd8fc39651"
 "checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
 "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
 "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
 "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
-"checksum selectors 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd81c2af3eba55ccc7048696c517a0e594ae9a4045b8fb3cc6ad80cd6d65ca5"
+"checksum selectors 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9eee17ca1807581fc4cf0bfddda311dc421f295a71314b9276ecc787cc63ed6f"
 "checksum serde 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bfdad8985ce7708e21ada7f3f188a0079de4f8e239155348a024e31f13cddf86"
 "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
 "checksum string_cache 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "32e79c75e2fc7bbe0cd0bafa9eeacef16a09e269e8518382a7283904c105c20e"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
 "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
 "checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
 "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -14,12 +14,12 @@ app_units = "0.3"
 env_logger = "0.3"
 euclid = "0.10.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.12"
+selectors = "0.13"
 style = {path = "../../components/style", features = ["gecko"]}
 style_traits = {path = "../../components/style_traits"}
 url = "1.2"
--- a/servo/ports/geckolib/string_cache/Cargo.toml
+++ b/servo/ports/geckolib/string_cache/Cargo.toml
@@ -9,10 +9,10 @@ publish = false
 [lib]
 path = "lib.rs"
 
 [dependencies]
 cfg-if = "0.1.0"
 gecko_bindings = {version = "0.0.1", path = "../gecko_bindings"}
 heapsize = "0.3.5"
 libc = "0.2"
-selectors = "0.12"
+selectors = "0.13"
 serde = "0.8"
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -9,14 +9,14 @@ name = "style_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
 app_units = "0.3"
 cssparser = {version = "0.6", features = ["heap_size"]}
 euclid = "0.10.1"
 rustc-serialize = "0.3"
-selectors = {version = "0.12", features = ["heap_size"]}
+selectors = {version = "0.13", features = ["heap_size"]}
 string_cache = {version = "0.2.26", features = ["heap_size"]}
 style = {path = "../../../components/style"}
 style_traits = {path = "../../../components/style_traits"}
 url = {version = "1.2", features = ["heap_size"]}
 util = {path = "../../../components/util"}