servo: Merge #12924 - Update selectors to 0.10, with ToCss serialization (from servo:selectors-ser); r=nox
authorSimon Sapin <simon.sapin@exyr.org>
Fri, 19 Aug 2016 13:01:29 -0500
changeset 339520 2f738ecf0d836b8e076946ddb770b23a015a3542
parent 339519 182c86c7153fb227043e76ba6283f9fb3161a52d
child 339521 84109d55f39c1374033335888637f31dbad364c5
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)
reviewersnox
servo: Merge #12924 - Update selectors to 0.10, with ToCss serialization (from servo:selectors-ser); r=nox <!-- Please describe your changes on the following line: --> r? @emilio --- <!-- 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 - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 07b217368f6f2ec35450edab9c6c29091aa16433
servo/components/layout/Cargo.toml
servo/components/script/Cargo.toml
servo/components/script/dom/element.rs
servo/components/script/layout_wrapper.rs
servo/components/script_layout_interface/Cargo.toml
servo/components/servo/Cargo.lock
servo/components/style/Cargo.toml
servo/components/style/gecko_selector_impl.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/restyle_hints.rs
servo/components/style/servo_selector_impl.rs
servo/components/style/stylesheets.rs
servo/ports/cef/Cargo.lock
servo/ports/geckolib/Cargo.lock
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/string_cache/Cargo.toml
servo/ports/geckolib/string_cache/namespace.rs
servo/ports/geckolib/wrapper.rs
servo/tests/unit/style/Cargo.toml
servo/tests/unit/style/parsing/mod.rs
servo/tests/unit/style/parsing/selectors.rs
servo/tests/unit/style/stylesheets.rs
--- 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.9", features = ["heap_size"]}
+selectors = {version = "0.10", features = ["heap_size"]}
 serde_macros = "0.8"
 smallvec = "0.1"
 string_cache = {version = "0.2.23", 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
@@ -57,17 +57,17 @@ profile_traits = {path = "../profile_tra
 rand = "0.3"
 range = {path = "../range"}
 ref_filter_map = "1.0"
 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.9", features = ["heap_size"]}
+selectors = {version = "0.10", features = ["heap_size"]}
 serde = "0.8"
 smallvec = "0.1"
 string_cache = {version = "0.2.23", 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", features = ["v4"]}
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -2245,17 +2245,17 @@ impl<'a> ::selectors::MatchAttrGeneric f
             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)
+                self.get_attribute(&ns.url, 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())
                 })
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -478,17 +478,17 @@ impl<'le> ::selectors::MatchAttrGeneric 
         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))
+                self.get_attr(&ns.url, 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))
             }
         }
@@ -965,17 +965,17 @@ impl<'le> ThreadSafeLayoutElement for Se
 /// not for inheritance (styles are inherited appropiately).
 impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> {
     type Impl = ServoSelectorImpl;
 
     fn match_attr<F>(&self, attr: &AttrSelector<ServoSelectorImpl>, 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))
+                self.get_attr(&ns.url, &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))
                 }
             }
         }
--- 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.9", features = ["heap_size"]}
+selectors = {version = "0.10", features = ["heap_size"]}
 string_cache = {version = "0.2.23", 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
@@ -785,17 +785,17 @@ dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "simd 0.1.0 (git+https://github.com/huonw/simd)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "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)",
  "util 0.0.1",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
  "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -951,17 +951,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "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)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "httparse"
 version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1157,20 +1157,20 @@ 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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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)",
  "util 0.0.1",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
 ]
@@ -1926,20 +1926,20 @@ dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.1.71 (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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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",
  "uuid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1962,18 +1962,18 @@ dependencies = [
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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"
 version = "0.0.1"
@@ -2011,28 +2011,28 @@ 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.9.0"
+version = "0.10.1"
 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.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.3 (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)",
  "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
 version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2199,17 +2199,17 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "string_cache"
-version = "0.2.23"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2233,38 +2233,38 @@ dependencies = [
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.32 (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",
  "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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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)",
 ]
 
 [[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.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.9.0 (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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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]]
 name = "style_traits"
@@ -2693,17 +2693,17 @@ name = "xml5ever"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [metadata]
 "checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
 "checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8"
 "checksum android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f717214f8b7bac58e0fcfc2efcd716353b487a73f44935d7eab4e7b8f7d90778"
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -33,21 +33,21 @@ heapsize = {version = "0.3.0", optional 
 heapsize_plugin = {version = "0.1.2", optional = true}
 lazy_static = "0.2"
 log = "0.3.5"
 matches = "0.1"
 num-traits = "0.1.32"
 ordered-float = "0.2.2"
 rand = "0.3"
 rustc-serialize = "0.3"
-selectors = "0.9"
+selectors = "0.10.1"
 serde = {version = "0.8", optional = true}
 serde_macros = {version = "0.8", optional = true}
 smallvec = "0.1"
-string_cache = {version = "0.2.23", features = ["heap_size"], optional = true}
+string_cache = {version = "0.2.24", features = ["heap_size"], optional = true}
 style_traits = {path = "../style_traits"}
 time = "0.1"
 url = "1.2"
 util = {path = "../util"}
 plugins = {path = "../plugins", optional = true}
 
 [target.'cfg(windows)'.dependencies]
 kernel32-sys = "0.2"
--- a/servo/components/style/gecko_selector_impl.rs
+++ b/servo/components/style/gecko_selector_impl.rs
@@ -1,16 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+use cssparser::ToCss;
 use element_state::ElementState;
 use selector_impl::PseudoElementCascadeType;
 use selector_impl::{attr_exists_selector_is_shareable, attr_equals_selector_is_shareable};
 use selectors::parser::{ParserContext, SelectorImpl, AttrSelector};
+use std::fmt;
 use string_cache::{Atom, WeakAtom, Namespace, WeakNamespace};
 use stylesheets::Stylesheet;
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct GeckoSelectorImpl;
 
 /// NOTE: The boolean field represents whether this element is an anonymous box.
 ///
@@ -88,32 +90,62 @@ impl PseudoElement {
         }
 
         include!("generated/gecko_pseudo_element_helper.rs");
 
         None
     }
 }
 
+impl ToCss for PseudoElement {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        // FIXME: why does the atom contain one colon? Pseudo-element has two
+        debug_assert!(self.0.as_slice().starts_with(&[b':' as u16]) &&
+                      !self.0.as_slice().starts_with(&[b':' as u16, b':' as u16]));
+        try!(dest.write_char(':'));
+        write!(dest, "{}", self.0)
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum NonTSPseudoClass {
     AnyLink,
     Link,
     Visited,
     Active,
     Focus,
     Hover,
     Enabled,
     Disabled,
     Checked,
     Indeterminate,
     ReadWrite,
     ReadOnly,
 }
 
+impl ToCss for NonTSPseudoClass {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        use self::NonTSPseudoClass::*;
+        dest.write_str(match *self {
+            AnyLink => ":any-link",
+            Link => ":link",
+            Visited => ":visited",
+            Active => ":active",
+            Focus => ":focus",
+            Hover => ":hover",
+            Enabled => ":enabled",
+            Disabled => ":disabled",
+            Checked => ":checked",
+            Indeterminate => ":indeterminate",
+            ReadWrite => ":read-write",
+            ReadOnly => ":read-only",
+        })
+    }
+}
+
 impl NonTSPseudoClass {
     pub fn state_flag(&self) -> ElementState {
         use element_state::*;
         use self::NonTSPseudoClass::*;
         match *self {
             Active => IN_ACTIVE_STATE,
             Focus => IN_FOCUS_STATE,
             Hover => IN_HOVER_STATE,
@@ -130,18 +162,19 @@ impl NonTSPseudoClass {
     }
 }
 
 impl SelectorImpl for GeckoSelectorImpl {
     type AttrValue = Atom;
     type Identifier = Atom;
     type ClassName = Atom;
     type LocalName = Atom;
-    type Namespace = Namespace;
-    type BorrowedNamespace = WeakNamespace;
+    type NamespacePrefix = Atom;
+    type NamespaceUrl = Namespace;
+    type BorrowedNamespaceUrl = WeakNamespace;
     type BorrowedLocalName = WeakAtom;
 
     type PseudoElement = PseudoElement;
     type NonTSPseudoClass = NonTSPseudoClass;
 
     fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector<Self>) -> bool {
         attr_exists_selector_is_shareable(attr_selector)
     }
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -463,17 +463,17 @@ fn append_serialization<'a, W, I>(dest: 
     try!(handle_first_serialization(dest, is_first_serialization));
 
     // Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
     // values, they no longer use the shared property name "overflow" and must be handled differently
     if shorthands::is_overflow_shorthand(&appendable_value) {
         return append_declaration_value(dest, appendable_value, is_important);
     }
 
-    write!(dest, "{}:", property_name);
+    try!(write!(dest, "{}:", property_name));
 
     // for normal parsed values, add a space between key: and value
     match &appendable_value {
         &AppendableValue::Css(_) => {
             try!(write!(dest, " "))
         },
         &AppendableValue::Declaration(decl) => {
             if !decl.value_is_unparsed() {
--- a/servo/components/style/restyle_hints.rs
+++ b/servo/components/style/restyle_hints.rs
@@ -215,17 +215,17 @@ impl<'a, E> Element for ElementWrapper<'
     fn is_html_element_in_html_document(&self) -> bool {
         self.element.is_html_element_in_html_document()
     }
 
     fn get_local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName {
         self.element.get_local_name()
     }
 
-    fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespace {
+    fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl {
         self.element.get_namespace()
     }
 
     fn get_id(&self) -> Option<Atom> {
         match self.snapshot {
             Some(snapshot) if snapshot.has_attrs()
                 => snapshot.id_attr(),
             _   => self.element.get_id()
--- a/servo/components/style/servo_selector_impl.rs
+++ b/servo/components/style/servo_selector_impl.rs
@@ -1,21 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use attr::{AttrIdentifier, AttrValue};
+use cssparser::ToCss;
 use element_state::ElementState;
 use error_reporting::StdoutErrorReporter;
 use parser::ParserContextExtraData;
 use restyle_hints::ElementSnapshot;
 use selector_impl::{ElementExt, PseudoElementCascadeType, TheSelectorImpl};
 use selector_impl::{attr_exists_selector_is_shareable, attr_equals_selector_is_shareable};
 use selectors::parser::{AttrSelector, ParserContext, SelectorImpl};
 use selectors::{Element, MatchAttrGeneric};
+use std::fmt;
 use std::process;
 use string_cache::{Atom, Namespace};
 use stylesheets::{Stylesheet, Origin};
 use url::Url;
 use util::opts;
 use util::resource_files::read_resource_file;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -23,16 +25,30 @@ use util::resource_files::read_resource_
 pub enum PseudoElement {
     Before,
     After,
     Selection,
     DetailsSummary,
     DetailsContent,
 }
 
+impl ToCss for PseudoElement {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        use self::PseudoElement::*;
+        dest.write_str(match *self {
+            Before => "::before",
+            After => "::after",
+            Selection => "::selection",
+            DetailsSummary => "::-servo-details-summary",
+            DetailsContent => "::-servo-details-content",
+        })
+    }
+}
+
+
 impl PseudoElement {
     #[inline]
     pub fn is_before_or_after(&self) -> bool {
         match *self {
             PseudoElement::Before |
             PseudoElement::After => true,
             _ => false,
         }
@@ -65,16 +81,39 @@ pub enum NonTSPseudoClass {
     Indeterminate,
     ServoNonZeroBorder,
     ReadWrite,
     ReadOnly,
     PlaceholderShown,
     Target,
 }
 
+impl ToCss for NonTSPseudoClass {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        use self::NonTSPseudoClass::*;
+        dest.write_str(match *self {
+            AnyLink => ":any-link",
+            Link => ":link",
+            Visited => ":visited",
+            Active => ":active",
+            Focus => ":focus",
+            Hover => ":hover",
+            Enabled => ":enabled",
+            Disabled => ":disabled",
+            Checked => ":checked",
+            Indeterminate => ":indeterminate",
+            ReadWrite => ":read-write",
+            ReadOnly => ":read-only",
+            PlaceholderShown => ":placeholder-shown",
+            Target => ":target",
+            ServoNonZeroBorder => ":-servo-nonzero-border",
+        })
+    }
+}
+
 impl NonTSPseudoClass {
     pub fn state_flag(&self) -> ElementState {
         use element_state::*;
         use self::NonTSPseudoClass::*;
         match *self {
             Active => IN_ACTIVE_STATE,
             Focus => IN_FOCUS_STATE,
             Hover => IN_HOVER_STATE,
@@ -101,19 +140,20 @@ pub struct ServoSelectorImpl;
 impl SelectorImpl for ServoSelectorImpl {
     type PseudoElement = PseudoElement;
     type NonTSPseudoClass = NonTSPseudoClass;
 
     type AttrValue = String;
     type Identifier = Atom;
     type ClassName = Atom;
     type LocalName = Atom;
-    type Namespace = Namespace;
+    type NamespacePrefix = Atom;
+    type NamespaceUrl = Namespace;
     type BorrowedLocalName = Atom;
-    type BorrowedNamespace = Namespace;
+    type BorrowedNamespaceUrl = Namespace;
 
     fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector<Self>) -> bool {
         attr_exists_selector_is_shareable(attr_selector)
     }
 
     fn attr_equals_selector_is_shareable(attr_selector: &AttrSelector<Self>,
                                          value: &Self::AttrValue) -> bool {
         attr_equals_selector_is_shareable(attr_selector, value)
@@ -278,17 +318,17 @@ impl MatchAttrGeneric for ServoElementSn
 
     fn match_attr<F>(&self, attr: &AttrSelector<ServoSelectorImpl>, test: F) -> bool
         where F: Fn(&str) -> bool
     {
         use selectors::parser::NamespaceConstraint;
         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.get_attr(ns, local_name),
+            NamespaceConstraint::Specific(ref ns) => self.get_attr(&ns.url, local_name),
             NamespaceConstraint::Any => self.get_attr_ignore_ns(local_name),
         }.map_or(false, |v| test(v))
     }
 }
 
 impl<E: Element<Impl=TheSelectorImpl>> ElementExt for E {
     type Snapshot = ServoElementSnapshot;
 
--- a/servo/components/style/stylesheets.rs
+++ b/servo/components/style/stylesheets.rs
@@ -53,17 +53,21 @@ pub struct Stylesheet {
     pub dirty_on_viewport_size_change: bool,
 }
 
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum CSSRule {
     Charset(String),
-    Namespace(Option<String>, Namespace),
+    Namespace {
+        /// `None` for the default Namespace
+        prefix: Option<Atom>,
+        url: Namespace,
+    },
     Style(StyleRule),
     Media(MediaRule),
     FontFace(FontFaceRule),
     Viewport(ViewportRule),
     Keyframes(KeyframesRule),
 }
 
 
@@ -138,23 +142,23 @@ impl Stylesheet {
         input.look_for_viewport_percentages();
 
         let mut rules = vec![];
         {
             let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
             while let Some(result) = iter.next() {
                 match result {
                     Ok(rule) => {
-                        if let CSSRule::Namespace(ref prefix, ref namespace) = rule {
+                        if let CSSRule::Namespace { ref prefix, ref url } = rule {
                             if let Some(prefix) = prefix.as_ref() {
                                 iter.parser.context.selector_context.namespace_prefixes.insert(
-                                    prefix.clone(), namespace.clone());
+                                    prefix.clone(), url.clone());
                             } else {
                                 iter.parser.context.selector_context.default_namespace =
-                                    Some(namespace.clone());
+                                    Some(url.clone());
                             }
                         }
 
                         rules.push(rule);
                     }
                     Err(range) => {
                         let pos = range.start;
                         let message = format!("Invalid rule: '{}'", iter.input.slice(range));
@@ -430,19 +434,22 @@ impl<'a> AtRuleParser for TopLevelRulePa
                 } else {
                     return Err(())  // "@import must be before any rule but @charset"
                 }
             },
             "namespace" => {
                 if self.state.get() <= State::Namespaces {
                     self.state.set(State::Namespaces);
 
-                    let prefix = input.try(|input| input.expect_ident()).ok().map(|p| p.into_owned());
+                    let prefix = input.try(|input| input.expect_ident()).ok().map(|p| p.into());
                     let url = Namespace(Atom::from(try!(input.expect_url_or_string())));
-                    return Ok(AtRuleType::WithoutBlock(CSSRule::Namespace(prefix, url)))
+                    return Ok(AtRuleType::WithoutBlock(CSSRule::Namespace {
+                        prefix: prefix,
+                        url: url,
+                    }))
                 } else {
                     return Err(())  // "@namespace must be before any rule but @charset and @import"
                 }
             },
             _ => {}
         }
 
         self.state.set(State::Body);
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -702,17 +702,17 @@ dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "simd 0.1.0 (git+https://github.com/huonw/simd)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "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)",
  "util 0.0.1",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
  "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -859,17 +859,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "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)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "httparse"
 version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1065,20 +1065,20 @@ 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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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)",
  "util 0.0.1",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
 ]
@@ -1778,20 +1778,20 @@ dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "range 0.0.1",
  "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ref_slice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.1.71 (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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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",
  "uuid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.4.0 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1814,18 +1814,18 @@ dependencies = [
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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"
 version = "0.0.1"
@@ -1853,28 +1853,28 @@ 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.9.0"
+version = "0.10.1"
 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.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.3 (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)",
  "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
 version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2082,17 +2082,17 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "string_cache"
-version = "0.2.23"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2116,21 +2116,21 @@ dependencies = [
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.32 (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",
  "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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (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)",
 ]
 
 [[package]]
@@ -2553,17 +2553,17 @@ name = "xml5ever"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [metadata]
 "checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
 "checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8"
 "checksum android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f717214f8b7bac58e0fcfc2efcd716353b487a73f44935d7eab4e7b8f7d90778"
--- 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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gecko_bindings 0.0.1",
  "gecko_string_cache 0.2.20",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "selectors 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (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]]
 name = "aho-corasick"
@@ -165,17 +165,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.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "selectors 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (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"
 
@@ -306,41 +306,41 @@ 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.9.0"
+version = "0.10.1"
 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.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallvec"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "string_cache"
-version = "0.2.23"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -362,17 +362,17 @@ dependencies = [
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.2.3 (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.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.10.1 (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)",
 ]
 
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -14,13 +14,13 @@ app_units = "0.3"
 env_logger = "0.3"
 euclid = "0.9"
 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.9"
+selectors = "0.10"
 style = {path = "../../components/style", features = ["gecko"]}
 style_traits = {path = "../../components/style_traits"}
 url = "1.2"
 util = {path = "../../components/util"}
--- 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.9"
+selectors = "0.10"
 serde = "0.8"
--- a/servo/ports/geckolib/string_cache/namespace.rs
+++ b/servo/ports/geckolib/string_cache/namespace.rs
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use gecko_bindings::structs::nsIAtom;
 use selectors::bloom::BloomHash;
 use std::borrow::Borrow;
+use std::fmt;
 use std::ops::Deref;
 use {Atom, WeakAtom};
 
 #[macro_export]
 macro_rules! ns {
     () => { $crate::Namespace(atom!("")) }
 }
 
@@ -24,16 +25,22 @@ impl Deref for Namespace {
     fn deref(&self) -> &WeakNamespace {
         let weak: *const WeakAtom = &*self.0;
         unsafe {
             &*(weak as *const WeakNamespace)
         }
     }
 }
 
+impl fmt::Display for Namespace {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(w)
+    }
+}
+
 impl Borrow<WeakNamespace> for Namespace {
     #[inline]
     fn borrow(&self) -> &WeakNamespace {
         self
     }
 }
 
 impl WeakNamespace {
--- a/servo/ports/geckolib/wrapper.rs
+++ b/servo/ports/geckolib/wrapper.rs
@@ -582,17 +582,17 @@ pub trait AttrSelectorHelpers {
     fn ns_or_null(&self) -> *mut nsIAtom;
     fn select_name(&self, is_html_element_in_html_document: bool) -> *mut nsIAtom;
 }
 
 impl AttrSelectorHelpers for AttrSelector<GeckoSelectorImpl> {
     fn ns_or_null(&self) -> *mut nsIAtom {
         match self.namespace {
             NamespaceConstraint::Any => ptr::null_mut(),
-            NamespaceConstraint::Specific(ref ns) => ns.0.as_ptr(),
+            NamespaceConstraint::Specific(ref ns) => ns.url.0.as_ptr(),
         }
     }
 
     fn select_name(&self, is_html_element_in_html_document: bool) -> *mut nsIAtom {
         if is_html_element_in_html_document {
             self.lower_name.as_ptr()
         } else {
             self.name.as_ptr()
--- 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.5.7", features = ["heap_size"]}
 euclid = "0.9"
 rustc-serialize = "0.3"
-selectors = {version = "0.9", features = ["heap_size"]}
+selectors = {version = "0.10", features = ["heap_size"]}
 string_cache = {version = "0.2.23", features = ["heap_size"]}
 style = {path = "../../../components/style"}
 style_traits = {path = "../../../components/style_traits"}
 url = {version = "1.2", features = ["heap_size"]}
 util = {path = "../../../components/util"}
--- a/servo/tests/unit/style/parsing/mod.rs
+++ b/servo/tests/unit/style/parsing/mod.rs
@@ -10,24 +10,28 @@ fn parse<T, F: Fn(&mut Parser) -> Result
     let mut parser = Parser::new(s);
     f(&mut parser)
 }
 
 
 // This is a macro so that the file/line information
 // is preserved in the panic
 macro_rules! assert_roundtrip {
+    ($fun:expr, $string:expr) => {
+        assert_roundtrip!($fun, $string, $string);
+    };
     ($fun:expr, $input:expr, $output:expr) => {
         let parsed = $crate::parsing::parse($fun, $input)
                         .expect(&format!("Failed to parse {}", $input));
         let serialized = ::cssparser::ToCss::to_css_string(&parsed);
         assert_eq!(serialized, $output);
 
         let re_parsed = $crate::parsing::parse($fun, &serialized)
                         .expect(&format!("Failed to parse serialization {}", $input));
         let re_serialized = ::cssparser::ToCss::to_css_string(&re_parsed);
         assert_eq!(serialized, re_serialized);
     }
 }
 
 
 mod basic_shape;
 mod position;
+mod selectors;
new file mode 100644
--- /dev/null
+++ b/servo/tests/unit/style/parsing/selectors.rs
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use cssparser::Parser;
+use selectors::parser::{Selector, ParserContext, parse_selector_list};
+use style::selector_impl::TheSelectorImpl;
+
+fn parse(input: &mut Parser) -> Result<Selector<TheSelectorImpl>, ()> {
+    let mut context = ParserContext::new();
+    context.in_user_agent_stylesheet = true;
+    context.namespace_prefixes.insert("svg".into(), ns!(svg));
+    parse_selector_list(&context, input).map(|mut vec| vec.pop().unwrap())
+}
+
+#[test]
+fn test_selectors() {
+    assert_roundtrip!(parse, "div");
+    assert_roundtrip!(parse, "svg|circle");
+    assert_roundtrip!(parse, "p:before", "p::before");
+    assert_roundtrip!(parse, "[border = \"0\"]:-servo-nonzero-border ~ ::-servo-details-summary");
+}
--- a/servo/tests/unit/style/stylesheets.rs
+++ b/servo/tests/unit/style/stylesheets.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use cssparser::{self, Parser, SourcePosition};
 use media_queries::CSSErrorReporterTest;
 use selectors::parser::*;
 use std::borrow::ToOwned;
 use std::sync::Arc;
 use std::sync::Mutex;
-use string_cache::{Atom, Namespace};
+use string_cache::{Atom, Namespace as NsAtom};
 use style::error_reporting::ParseErrorReporter;
 use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
 use style::parser::ParserContextExtraData;
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands};
 use style::stylesheets::{Stylesheet, CSSRule, StyleRule, KeyframesRule, Origin};
 use style::values::specified::{LengthOrPercentageOrAuto, Percentage};
 use url::Url;
 
@@ -33,31 +33,40 @@ fn test_parse_stylesheet() {
     let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent,
                                           Box::new(CSSErrorReporterTest),
                                           ParserContextExtraData::default());
     assert_eq!(stylesheet, Stylesheet {
         origin: Origin::UserAgent,
         media: None,
         dirty_on_viewport_size_change: false,
         rules: vec![
-            CSSRule::Namespace(None, Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+            CSSRule::Namespace {
+                prefix: None,
+                url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+            },
             CSSRule::Style(StyleRule {
                 selectors: vec![
                     Selector {
                         compound_selectors: Arc::new(CompoundSelector {
                             simple_selectors: vec![
-                                SimpleSelector::Namespace(Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+                                SimpleSelector::Namespace(Namespace {
+                                    prefix: None,
+                                    url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+                                }),
                                 SimpleSelector::LocalName(LocalName {
                                     name: atom!("input"),
                                     lower_name: atom!("input"),
                                 }),
                                 SimpleSelector::AttrEqual(AttrSelector {
                                     name: atom!("type"),
                                     lower_name: atom!("type"),
-                                    namespace: NamespaceConstraint::Specific(ns!()),
+                                    namespace: NamespaceConstraint::Specific(Namespace {
+                                        prefix: None,
+                                        url: ns!()
+                                    }),
                                 }, "hidden".to_owned(), CaseSensitivity::CaseInsensitive)
                             ],
                             next: None,
                         }),
                         pseudo_element: None,
                         specificity: (0 << 20) + (1 << 10) + (1 << 0),
                     },
                 ],
@@ -69,31 +78,37 @@ fn test_parse_stylesheet() {
                     ]),
                 },
             }),
             CSSRule::Style(StyleRule {
                 selectors: vec![
                     Selector {
                         compound_selectors: Arc::new(CompoundSelector {
                             simple_selectors: vec![
-                                SimpleSelector::Namespace(Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+                                SimpleSelector::Namespace(Namespace {
+                                    prefix: None,
+                                    url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+                                }),
                                 SimpleSelector::LocalName(LocalName {
                                     name: atom!("html"),
                                     lower_name: atom!("html"),
                                 }),
                             ],
                             next: None,
                         }),
                         pseudo_element: None,
                         specificity: (0 << 20) + (0 << 10) + (1 << 0),
                     },
                     Selector {
                         compound_selectors: Arc::new(CompoundSelector {
                             simple_selectors: vec![
-                                SimpleSelector::Namespace(Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+                                SimpleSelector::Namespace(Namespace {
+                                    prefix: None,
+                                    url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+                                }),
                                 SimpleSelector::LocalName(LocalName {
                                     name: atom!("body"),
                                     lower_name: atom!("body"),
                                 }),
                             ],
                             next: None,
                         }),
                         pseudo_element: None,
@@ -108,22 +123,28 @@ fn test_parse_stylesheet() {
                     important: Arc::new(vec![]),
                 },
             }),
             CSSRule::Style(StyleRule {
                 selectors: vec![
                     Selector {
                         compound_selectors: Arc::new(CompoundSelector {
                             simple_selectors: vec![
-                                SimpleSelector::Namespace(Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+                                SimpleSelector::Namespace(Namespace {
+                                    prefix: None,
+                                    url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+                                }),
                                 SimpleSelector::Class(Atom::from("ok")),
                             ],
                             next: Some((Arc::new(CompoundSelector {
                                 simple_selectors: vec![
-                                    SimpleSelector::Namespace(Namespace(Atom::from("http://www.w3.org/1999/xhtml"))),
+                                    SimpleSelector::Namespace(Namespace {
+                                        prefix: None,
+                                        url: NsAtom(Atom::from("http://www.w3.org/1999/xhtml"))
+                                    }),
                                     SimpleSelector::ID(Atom::from("d1")),
                                 ],
                                 next: None,
                             }), Combinator::Child)),
                         }),
                         pseudo_element: None,
                         specificity: (1 << 20) + (1 << 10) + (0 << 0),
                     },