servo: Merge #12515 - Make the style crate more concrete (from servo:concrete-style); r=bholley
authorSimon Sapin <simon.sapin@exyr.org>
Wed, 20 Jul 2016 02:58:34 -0500
changeset 339393 c240fafa26f6fdedc44dd6c3a7f3d172536e6b87
parent 339392 90c92334a916642e221b3ff3c4477f60bf226a90
child 339394 bd9a1a5e45a88a8b8497f8072a3c458a655bc503
push id86548
push userkwierso@gmail.com
push dateSat, 04 Feb 2017 01:35:21 +0000
treeherdermozilla-inbound@e7b96d015d03 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
servo: Merge #12515 - Make the style crate more concrete (from servo:concrete-style); r=bholley Background: The changes to Servo code to support Stylo began in the `selectors` crate with making pseudo-elements generic, defined be the user, so that different users (such as Servo and Gecko/Stylo) could have a different set of pseudo-elements supported and parsed. Adding a trait makes sense there since `selectors` is in its own repository and has others users (or at least [one](https://github.com/SimonSapin/kuchiki)). Then we kind of kept going with the same pattern and added a bunch of traits in the `style` crate to make everything generic, allowing Servo and Gecko/Stylo to do things differently. But we’ve also added a `gecko` Cargo feature to do conditional compilation, at first to enable or disable some CSS properties and values in the Mako templates. Since we’re doing conditional compilation anyway, it’s often easier and simpler to do it more (with `#[cfg(feature = "gecko")]` and `#[cfg(feature = "servo")]`) that to keep adding traits and making everything generic. When a type is generic, any method that we want to call on it needs to be part of some trait. ---- The first several commits move some code around, mostly from `geckolib` to `style` (with `#[cfg(feature = "gecko")]`) but otherwise don’t change much. The following commits remove some traits and many type parameters through the `style` crate, replacing them with pairs of conditionally-compiled API-compatible items (types, methods, …). Simplifying code is nice to make it more maintainable, but this is motivated by another change described in https://github.com/servo/servo/pull/12391#issuecomment-232183942. (Porting Servo for that change proved difficult because some code in the `style` crate was becoming generic over `String` vs `Atom`, and this PR will help make that concrete. That change, in turn, is motivated by removing geckolib’s `[replace]` override for string-cache, in order to enable using a single Cargo "workspace" in this repository.) r? @bholley --- <!-- 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 - [x] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require new tests because refactoring <!-- 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: 2d01d41a506bcbc7f26a2284b9f42390d6ef96ab
servo/components/gfx/font_context.rs
servo/components/layout/animation.rs
servo/components/layout/block.rs
servo/components/layout/construct.rs
servo/components/layout/context.rs
servo/components/layout/data.rs
servo/components/layout/display_list_builder.rs
servo/components/layout/flex.rs
servo/components/layout/flow.rs
servo/components/layout/fragment.rs
servo/components/layout/generated_content.rs
servo/components/layout/inline.rs
servo/components/layout/list_item.rs
servo/components/layout/model.rs
servo/components/layout/multicol.rs
servo/components/layout/query.rs
servo/components/layout/table.rs
servo/components/layout/table_caption.rs
servo/components/layout/table_cell.rs
servo/components/layout/table_colgroup.rs
servo/components/layout/table_row.rs
servo/components/layout/table_rowgroup.rs
servo/components/layout/table_wrapper.rs
servo/components/layout/text.rs
servo/components/layout/traversal.rs
servo/components/layout/wrapper.rs
servo/components/layout_thread/lib.rs
servo/components/script/dom/document.rs
servo/components/script/dom/htmllinkelement.rs
servo/components/script/dom/htmlmetaelement.rs
servo/components/script/dom/htmlstyleelement.rs
servo/components/script/layout_wrapper.rs
servo/components/script_layout_interface/lib.rs
servo/components/script_layout_interface/message.rs
servo/components/script_layout_interface/restyle_damage.rs
servo/components/script_layout_interface/wrapper_traits.rs
servo/components/style/animation.rs
servo/components/style/context.rs
servo/components/style/data.rs
servo/components/style/dom.rs
servo/components/style/gecko_glue.rs
servo/components/style/gecko_selector_impl.rs
servo/components/style/gecko_values.rs
servo/components/style/lib.rs
servo/components/style/matching.rs
servo/components/style/properties/build.py
servo/components/style/properties/data.py
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/color.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_box.mako.rs
servo/components/style/properties/longhand/inherited_table.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/properties/longhand/outline.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/restyle_hints.rs
servo/components/style/selector_impl.rs
servo/components/style/selector_matching.rs
servo/components/style/servo.rs
servo/components/style/servo_selector_impl.rs
servo/components/style/stylesheets.rs
servo/components/style/traversal.rs
servo/components/style/values.rs
servo/components/style/viewport.rs
servo/docs/components/style.md
servo/ports/geckolib/Cargo.lock
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/build.rs
servo/ports/geckolib/context.rs
servo/ports/geckolib/data.rs
servo/ports/geckolib/generate_properties_rs.py
servo/ports/geckolib/glue.rs
servo/ports/geckolib/lib.rs
servo/ports/geckolib/properties.mako.rs
servo/ports/geckolib/selector_impl.rs
servo/ports/geckolib/traversal.rs
servo/ports/geckolib/values.rs
servo/ports/geckolib/wrapper.rs
servo/tests/unit/style/lib.rs
servo/tests/unit/style/media_queries.rs
servo/tests/unit/style/stylesheets.rs
servo/tests/unit/style/viewport.rs
--- a/servo/components/gfx/font_context.rs
+++ b/servo/components/gfx/font_context.rs
@@ -20,17 +20,17 @@ use std::cell::RefCell;
 use std::collections::HashMap;
 use std::default::Default;
 use std::hash::{BuildHasherDefault, Hash, Hasher};
 use std::rc::Rc;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 use string_cache::Atom;
 use style::computed_values::{font_style, font_variant};
-use style::properties::style_structs::ServoFont;
+use style::properties::style_structs;
 use webrender_traits;
 
 #[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
 fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
     ScaledFont::new(BackendType::Skia, FontInfo::FontData(&template.bytes),
                     pt_size.to_f32_px())
 }
 
@@ -136,17 +136,17 @@ impl FontContext {
         self.paint_font_cache.clear();
         self.layout_font_group_cache.clear();
         self.epoch = current_epoch
     }
 
     /// Create a group of fonts for use in layout calculations. May return
     /// a cached font if this font instance has already been used by
     /// this context.
-    pub fn layout_font_group_for_style(&mut self, style: Arc<ServoFont>)
+    pub fn layout_font_group_for_style(&mut self, style: Arc<style_structs::Font>)
                                        -> Rc<FontGroup> {
         self.expire_font_caches_if_necessary();
 
         let layout_font_group_cache_key = LayoutFontGroupCacheKey {
             pointer: style.clone(),
             size: style.font_size,
         };
         if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
@@ -292,17 +292,17 @@ impl HeapSizeOf for FontContext {
     fn heap_size_of_children(&self) -> usize {
         // FIXME(njn): Measure other fields eventually.
         self.platform_handle.heap_size_of_children()
     }
 }
 
 #[derive(Debug)]
 struct LayoutFontGroupCacheKey {
-    pointer: Arc<ServoFont>,
+    pointer: Arc<style_structs::Font>,
     size: Au,
 }
 
 impl PartialEq for LayoutFontGroupCacheKey {
     fn eq(&self, other: &LayoutFontGroupCacheKey) -> bool {
         self.pointer == other.pointer && self.size == other.size
     }
 }
--- a/servo/components/layout/animation.rs
+++ b/servo/components/layout/animation.rs
@@ -9,27 +9,26 @@ use flow::{self, Flow};
 use gfx::display_list::OpaqueNode;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::PipelineId;
 use script_layout_interface::restyle_damage::RestyleDamage;
 use script_traits::{AnimationState, LayoutMsg as ConstellationMsg};
 use std::collections::HashMap;
 use std::sync::mpsc::Receiver;
 use style::animation::{Animation, update_style_for_animation};
-use style::selector_impl::{SelectorImplExt, ServoSelectorImpl};
 use time;
 
 /// Processes any new animations that were discovered after style recalculation.
 /// Also expire any old animations that have completed, inserting them into
 /// `expired_animations`.
-pub fn update_animation_state<Impl: SelectorImplExt>(constellation_chan: &IpcSender<ConstellationMsg>,
-                                                     running_animations: &mut HashMap<OpaqueNode, Vec<Animation<Impl>>>,
-                                                     expired_animations: &mut HashMap<OpaqueNode, Vec<Animation<Impl>>>,
-                                                     new_animations_receiver: &Receiver<Animation<Impl>>,
-                                                     pipeline_id: PipelineId) {
+pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
+                              running_animations: &mut HashMap<OpaqueNode, Vec<Animation>>,
+                              expired_animations: &mut HashMap<OpaqueNode, Vec<Animation>>,
+                              new_animations_receiver: &Receiver<Animation>,
+                              pipeline_id: PipelineId) {
     let mut new_running_animations = vec![];
     while let Ok(animation) = new_animations_receiver.try_recv() {
         let mut should_push = true;
         if let Animation::Keyframes(ref node, ref name, ref state) = animation {
             // If the animation was already present in the list for the
             // node, just update its state, else push the new animation to
             // run.
             if let Some(ref mut animations) = running_animations.get_mut(node) {
@@ -120,17 +119,17 @@ pub fn update_animation_state<Impl: Sele
 /// Recalculates style for a set of animations. This does *not* run with the DOM
 /// lock held.
 // NB: This is specific for ServoSelectorImpl, since the layout context and the
 // flows are ServoSelectorImpl specific too. If that goes away at some point,
 // this should be made generic.
 pub fn recalc_style_for_animations(context: &SharedLayoutContext,
                                    flow: &mut Flow,
                                    animations: &HashMap<OpaqueNode,
-                                                        Vec<Animation<ServoSelectorImpl>>>) {
+                                                        Vec<Animation>>) {
     let mut damage = RestyleDamage::empty();
     flow.mutate_fragments(&mut |fragment| {
         if let Some(ref animations) = animations.get(&fragment.node) {
             for animation in animations.iter() {
                 update_style_for_animation(&context.style_context,
                                            animation,
                                            &mut fragment.style,
                                            Some(&mut damage));
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -51,20 +51,19 @@ use model::{CollapsibleMargins, MaybeAut
 use model::{self, IntrinsicISizes, MarginCollapseInfo};
 use rustc_serialize::{Encodable, Encoder};
 use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp::{max, min};
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x, overflow_y};
 use style::computed_values::{position, text_align, transform, transform_style};
-use style::context::StyleContext;
+use style::context::{SharedStyleContext, StyleContext};
 use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone};
 use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
 use util::geometry::MAX_RECT;
 
 /// The number of screens of data we're allowed to generate display lists for in each direction.
 const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
 
 /// Information specific to floated blocks.
--- a/servo/components/layout/construct.rs
+++ b/servo/components/layout/construct.rs
@@ -41,18 +41,18 @@ use std::borrow::ToOwned;
 use std::collections::LinkedList;
 use std::marker::PhantomData;
 use std::mem;
 use std::sync::Arc;
 use std::sync::atomic::Ordering;
 use style::computed_values::content::ContentItem;
 use style::computed_values::position;
 use style::computed_values::{caption_side, display, empty_cells, float, list_style_position};
-use style::properties::{self, ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::context::SharedStyleContext;
+use style::properties::{self, ServoComputedValues};
 use table::TableFlow;
 use table_caption::TableCaptionFlow;
 use table_cell::TableCellFlow;
 use table_colgroup::TableColGroupFlow;
 use table_row::TableRowFlow;
 use table_rowgroup::TableRowGroupFlow;
 use table_wrapper::TableWrapperFlow;
 use text::TextRunScanner;
--- a/servo/components/layout/context.rs
+++ b/servo/components/layout/context.rs
@@ -19,24 +19,22 @@ use ipc_channel::ipc::{self, IpcSharedMe
 use net_traits::image::base::Image;
 use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread, ImageResponse, ImageState};
 use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
 use std::cell::{RefCell, RefMut};
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use std::rc::Rc;
 use std::sync::{Arc, Mutex, RwLock};
-use style::context::{LocalStyleContext, StyleContext};
-use style::selector_impl::ServoSelectorImpl;
-use style::servo::SharedStyleContext;
+use style::context::{LocalStyleContext, StyleContext, SharedStyleContext};
 use url::Url;
 use util::opts;
 
 struct LocalLayoutContext {
-    style_context: LocalStyleContext<ServoSelectorImpl>,
+    style_context: LocalStyleContext,
 
     font_context: RefCell<FontContext>,
 }
 
 impl HeapSizeOf for LocalLayoutContext {
     // FIXME(njn): measure other fields eventually.
     fn heap_size_of_children(&self) -> usize {
         self.font_context.heap_size_of_children()
@@ -98,22 +96,22 @@ pub struct SharedLayoutContext {
                                                   BuildHasherDefault<FnvHasher>>>>,
 }
 
 pub struct LayoutContext<'a> {
     pub shared: &'a SharedLayoutContext,
     cached_local_layout_context: Rc<LocalLayoutContext>,
 }
 
-impl<'a> StyleContext<'a, ServoSelectorImpl> for LayoutContext<'a> {
+impl<'a> StyleContext<'a> for LayoutContext<'a> {
     fn shared_context(&self) -> &'a SharedStyleContext {
         &self.shared.style_context
     }
 
-    fn local_context(&self) -> &LocalStyleContext<ServoSelectorImpl> {
+    fn local_context(&self) -> &LocalStyleContext {
         &self.cached_local_layout_context.style_context
     }
 }
 
 impl<'a> LayoutContext<'a> {
     pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
         let local_context = create_or_get_local_context(shared_layout_context);
 
--- a/servo/components/layout/data.rs
+++ b/servo/components/layout/data.rs
@@ -1,15 +1,15 @@
 /* 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 construct::ConstructionResult;
 use script_layout_interface::restyle_damage::RestyleDamage;
-use style::servo::PrivateStyleData;
+use style::data::PrivateStyleData;
 
 /// Data that layout associates with a node.
 pub struct PrivateLayoutData {
     /// Data that the style system associates with a node. When the
     /// style system is being used standalone, this is all that hangs
     /// off the node. This must be first to permit the various
     /// transmuations between PrivateStyleData PrivateLayoutData.
     pub style_data: PrivateStyleData,
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -45,18 +45,18 @@ use std::{cmp, f32};
 use style::computed_values::filter::Filter;
 use style::computed_values::text_shadow::TextShadow;
 use style::computed_values::{_servo_overflow_clip_box as overflow_clip_box};
 use style::computed_values::{background_attachment, background_clip, background_origin};
 use style::computed_values::{background_repeat, background_size, border_style};
 use style::computed_values::{cursor, image_rendering, overflow_x, pointer_events, position};
 use style::computed_values::{transform, transform_style, visibility};
 use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
-use style::properties::style_structs::ServoBorder;
-use style::properties::{self, ComputedValues, ServoComputedValues};
+use style::properties::style_structs;
+use style::properties::{self, ServoComputedValues};
 use style::values::RGBA;
 use style::values::computed;
 use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto, LinearGradient};
 use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
 use style_traits::cursor::Cursor;
 use table_cell::CollapsedBordersForCell;
 use url::Url;
 use util::opts;
@@ -310,17 +310,17 @@ fn handle_overlapping_radii(size: &Size2
     let min_factor = top_factor.min(bottom_factor).min(left_factor).min(right_factor);
     if min_factor < 1.0 {
         radii.scale_by(min_factor)
     } else {
         *radii
     }
 }
 
-fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &ServoBorder) -> BorderRadii<Au> {
+fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &style_structs::Border) -> BorderRadii<Au> {
     // TODO(cgaebel): Support border radii even in the case of multiple border widths.
     // This is an extension of supporting elliptical radii. For now, all percentage
     // radii will be relative to the width.
 
     handle_overlapping_radii(&abs_bounds.size, &BorderRadii {
         top_left:     model::specified_border_radius(border_style.border_top_left_radius,
                                                      abs_bounds.size.width),
         top_right:    model::specified_border_radius(border_style.border_top_right_radius,
--- a/servo/components/layout/flex.rs
+++ b/servo/components/layout/flex.rs
@@ -20,19 +20,19 @@ use fragment::{Fragment, FragmentBorderB
 use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use layout_debug;
 use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint};
 use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp::max;
 use std::sync::Arc;
 use style::computed_values::flex_direction;
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 
 /// The size of an axis. May be a specified size, a min/max
 /// constraint, or an unlimited size
 #[derive(Debug)]
 enum AxisSize {
     Definite(Au),
     MinMax(MinMaxConstraint),
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -45,20 +45,20 @@ use rustc_serialize::{Encodable, Encoder
 use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
 use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode};
 use std::iter::Zip;
 use std::slice::IterMut;
 use std::sync::Arc;
 use std::sync::atomic::Ordering;
 use std::{fmt, mem, raw};
 use style::computed_values::{clear, display, empty_cells, float, position, overflow_x, text_align};
+use style::context::SharedStyleContext;
 use style::dom::TRestyleDamage;
 use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
-use style::properties::{self, ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::{self, ServoComputedValues};
 use style::values::computed::LengthOrPercentageOrAuto;
 use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
 use table_caption::TableCaptionFlow;
 use table_cell::TableCellFlow;
 use table_colgroup::TableColGroupFlow;
 use table_row::TableRowFlow;
 use table_rowgroup::TableRowGroupFlow;
 use table_wrapper::TableWrapperFlow;
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -39,17 +39,17 @@ use std::fmt;
 use std::sync::{Arc, Mutex};
 use style::arc_ptr_eq;
 use style::computed_values::content::ContentItem;
 use style::computed_values::{border_collapse, clear, color, display, mix_blend_mode};
 use style::computed_values::{overflow_wrap, overflow_x, position, text_decoration};
 use style::computed_values::{transform_style, vertical_align, white_space, word_break, z_index};
 use style::dom::TRestyleDamage;
 use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
+use style::properties::ServoComputedValues;
 use style::str::char_is_whitespace;
 use style::values::computed::LengthOrPercentageOrNone;
 use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
 use text;
 use text::TextRunScanner;
 use url::Url;
 
 /// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
--- a/servo/components/layout/generated_content.rs
+++ b/servo/components/layout/generated_content.rs
@@ -16,17 +16,17 @@ use gfx::display_list::OpaqueNode;
 use script_layout_interface::restyle_damage::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
 use script_layout_interface::wrapper_traits::PseudoElementType;
 use smallvec::SmallVec;
 use std::collections::{HashMap, LinkedList};
 use std::sync::Arc;
 use style::computed_values::content::ContentItem;
 use style::computed_values::{display, list_style_type};
 use style::dom::TRestyleDamage;
-use style::properties::{ComputedValues, ServoComputedValues};
+use style::properties::ServoComputedValues;
 use text::TextRunScanner;
 
 // Decimal styles per CSS-COUNTER-STYLES § 6.1:
 static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
 // TODO(pcwalton): `decimal-leading-zero`
 static ARABIC_INDIC: [char; 10] = [ '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩' ];
 // TODO(pcwalton): `armenian`, `upper-armenian`, `lower-armenian`
 static BENGALI: [char; 10] = [ '০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯' ];
--- a/servo/components/layout/inline.rs
+++ b/servo/components/layout/inline.rs
@@ -30,20 +30,19 @@ use script_layout_interface::restyle_dam
 use script_layout_interface::wrapper_traits::PseudoElementType;
 use std::cmp::max;
 use std::collections::VecDeque;
 use std::sync::Arc;
 use std::{fmt, i32, isize, mem};
 use style::arc_ptr_eq;
 use style::computed_values::{display, overflow_x, position, text_align, text_justify};
 use style::computed_values::{text_overflow, vertical_align, white_space};
-use style::context::StyleContext;
+use style::context::{SharedStyleContext, StyleContext};
 use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::computed::LengthOrPercentage;
 use text;
 use unicode_bidi;
 
 // From gfxFontConstants.h in Firefox
 static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;
 static FONT_SUPERSCRIPT_OFFSET_RATIO: f32 = 0.34;
 
--- a/servo/components/layout/list_item.rs
+++ b/servo/components/layout/list_item.rs
@@ -18,19 +18,19 @@ use fragment::Overflow;
 use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedContentInfo};
 use generated_content;
 use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use inline::InlineMetrics;
 use script_layout_interface::restyle_damage::RESOLVE_GENERATED_CONTENT;
 use std::sync::Arc;
 use style::computed_values::{list_style_type, position};
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use text;
 
 /// A block with the CSS `display` property equal to `list-item`.
 #[derive(Debug)]
 pub struct ListItemFlow {
     /// Data common to all block flows.
     pub block_flow: BlockFlow,
     /// The marker, if outside. (Markers that are inside are instead just fragments on the interior
--- a/servo/components/layout/model.rs
+++ b/servo/components/layout/model.rs
@@ -8,17 +8,17 @@
 
 use app_units::Au;
 use euclid::{Matrix4D, SideOffsets2D, Size2D};
 use fragment::Fragment;
 use std::cmp::{max, min};
 use std::fmt;
 use style::computed_values::transform::ComputedMatrix;
 use style::logical_geometry::LogicalMargin;
-use style::properties::{ComputedValues, ServoComputedValues};
+use style::properties::ServoComputedValues;
 use style::values::computed::{BorderRadiusSize, LengthOrPercentageOrAuto};
 use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrNone};
 
 /// A collapsible margin. See CSS 2.1 § 8.3.1.
 #[derive(Copy, Clone, Debug)]
 pub struct AdjoiningMargins {
     /// The value of the greatest positive margin.
     pub most_positive: Au,
--- a/servo/components/layout/multicol.rs
+++ b/servo/components/layout/multicol.rs
@@ -16,20 +16,19 @@ use flow::{Flow, FlowClass, OpaqueFlow, 
 use flow_ref::{self, FlowRef};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use std::cmp::{min, max};
 use std::fmt;
 use std::sync::Arc;
-use style::context::StyleContext;
+use style::context::{StyleContext, SharedStyleContext};
 use style::logical_geometry::LogicalSize;
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::computed::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 
 pub struct MulticolFlow {
     pub block_flow: BlockFlow,
 
     /// Length between the inline-start edge of a column and that of the next.
     /// That is, the used column-width + used column-gap.
     pub column_pitch: Au,
--- a/servo/components/layout/query.rs
+++ b/servo/components/layout/query.rs
@@ -26,21 +26,20 @@ use script_traits::LayoutMsg as Constell
 use script_traits::UntrustedNodeAddress;
 use sequential;
 use std::cmp::{min, max};
 use std::ops::Deref;
 use std::sync::{Arc, Mutex};
 use string_cache::Atom;
 use style::computed_values;
 use style::logical_geometry::{WritingMode, BlockFlowDirection, InlineBaseDirection};
-use style::properties::ComputedValues;
 use style::properties::longhands::{display, position};
 use style::properties::style_structs;
 use style::selector_impl::PseudoElement;
-use style::servo::Stylist;
+use style::selector_matching::Stylist;
 use style::values::LocalToCss;
 use style_traits::cursor::Cursor;
 use wrapper::ThreadSafeLayoutNodeHelpers;
 
 /// Mutable data belonging to the LayoutThread.
 ///
 /// This needs to be protected by a mutex so we can do fast RPCs.
 pub struct LayoutThreadData {
@@ -445,17 +444,17 @@ impl ParentOffsetBorderBoxIterator {
             node_border_box: Rect::zero(),
             parent_nodes: Vec::new(),
         }
     }
 }
 
 impl FragmentBorderBoxIterator for FragmentLocatingFragmentIterator {
     fn process(&mut self, fragment: &Fragment, _: i32, border_box: &Rect<Au>) {
-        let style_structs::ServoBorder {
+        let style_structs::Border {
             border_top_width: top_width,
             border_right_width: right_width,
             border_bottom_width: bottom_width,
             border_left_width: left_width,
             ..
         } = *fragment.style.get_border();
         self.client_rect.origin.y = top_width.to_px();
         self.client_rect.origin.x = left_width.to_px();
@@ -471,17 +470,17 @@ impl FragmentBorderBoxIterator for Fragm
 // https://drafts.csswg.org/cssom-view/#scrolling-area
 impl FragmentBorderBoxIterator for UnioningFragmentScrollAreaIterator {
     fn process(&mut self, fragment: &Fragment, level: i32, border_box: &Rect<Au>) {
         // In cases in which smaller child elements contain less padding than the parent
         // the a union of the two elements padding rectangles could result in an unwanted
         // increase in size. To work around this, we store the original elements padding
         // rectangle as `origin_rect` and the union of all child elements padding and
         // margin rectangles as `union_rect`.
-        let style_structs::ServoBorder {
+        let style_structs::Border {
             border_top_width: top_border,
             border_right_width: right_border,
             border_bottom_width: bottom_border,
             border_left_width: left_border,
             ..
         } = *fragment.style.get_border();
         let right_padding = (border_box.size.width - right_border - left_border).to_px();
         let bottom_padding = (border_box.size.height - bottom_border - top_border).to_px();
--- a/servo/components/layout/table.rs
+++ b/servo/components/layout/table.rs
@@ -21,19 +21,19 @@ use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};
 use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp;
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_spacing, table_layout};
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::CSSFloat;
 use style::values::computed::LengthOrPercentageOrAuto;
 use table_row::TableRowFlow;
 use table_row::{self, CellIntrinsicInlineSize, CollapsedBorder, CollapsedBorderProvenance};
 use table_wrapper::TableLayout;
 
 /// A table flow corresponded to the table's internal table fragment under a table wrapper flow.
 /// The properties `position`, `float`, and `margin-*` are used on the table wrapper fragment,
--- a/servo/components/layout/table_caption.rs
+++ b/servo/components/layout/table_caption.rs
@@ -13,19 +13,19 @@ use display_list_builder::DisplayListBui
 use euclid::Point2D;
 use flow::{Flow, FlowClass, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use std::fmt;
 use std::sync::Arc;
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
-use style::servo::SharedStyleContext;
 
 /// A table formatting context.
 pub struct TableCaptionFlow {
     pub block_flow: BlockFlow,
 }
 
 impl TableCaptionFlow {
     pub fn from_fragment(fragment: Fragment) -> TableCaptionFlow {
--- a/servo/components/layout/table_cell.rs
+++ b/servo/components/layout/table_cell.rs
@@ -19,19 +19,19 @@ use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::MaybeAuto;
 use script_layout_interface::restyle_damage::REFLOW;
 use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_top_style, vertical_align};
+use style::context::SharedStyleContext;
 use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use table::InternalTable;
 use table_row::{CollapsedBorder, CollapsedBorderProvenance};
 
 /// A table formatting context.
 #[derive(RustcEncodable)]
 pub struct TableCellFlow {
     /// Data common to all block flows.
     pub block_flow: BlockFlow,
--- a/servo/components/layout/table_colgroup.rs
+++ b/servo/components/layout/table_colgroup.rs
@@ -13,19 +13,19 @@ use euclid::Point2D;
 use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
 use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use layout_debug;
 use std::cmp::max;
 use std::fmt;
 use std::sync::Arc;
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
-use style::servo::SharedStyleContext;
 use style::values::computed::LengthOrPercentageOrAuto;
 
 /// A table formatting context.
 pub struct TableColGroupFlow {
     /// Data common to all flows.
     pub base: BaseFlow,
 
     /// The associated fragment.
--- a/servo/components/layout/table_row.rs
+++ b/servo/components/layout/table_row.rs
@@ -21,19 +21,19 @@ use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::MaybeAuto;
 use rustc_serialize::{Encodable, Encoder};
 use std::cmp::max;
 use std::fmt;
 use std::iter::{Enumerate, IntoIterator, Peekable};
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_spacing, border_top_style};
+use style::context::SharedStyleContext;
 use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::computed::LengthOrPercentageOrAuto;
 use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt};
 use table_cell::{CollapsedBordersForCell, TableCellFlow};
 
 /// A single row of a table.
 pub struct TableRowFlow {
     /// Fields common to all block flows.
     pub block_flow: BlockFlow,
--- a/servo/components/layout/table_rowgroup.rs
+++ b/servo/components/layout/table_rowgroup.rs
@@ -17,19 +17,19 @@ use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use rustc_serialize::{Encodable, Encoder};
 use std::fmt;
 use std::iter::{IntoIterator, Iterator, Peekable};
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_spacing};
+use style::context::SharedStyleContext;
 use style::logical_geometry::{LogicalSize, WritingMode};
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, TableLikeFlow};
 use table_row;
 
 /// A table formatting context.
 pub struct TableRowGroupFlow {
     /// Fields common to all block flows.
     pub block_flow: BlockFlow,
 
--- a/servo/components/layout/table_wrapper.rs
+++ b/servo/components/layout/table_wrapper.rs
@@ -26,19 +26,19 @@ use gfx::display_list::StackingContext;
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use model::MaybeAuto;
 use std::cmp::{max, min};
 use std::fmt;
 use std::ops::Add;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, table_layout};
+use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
-use style::properties::{ComputedValues, ServoComputedValues};
-use style::servo::SharedStyleContext;
+use style::properties::ServoComputedValues;
 use style::values::CSSFloat;
 use style::values::computed::LengthOrPercentageOrAuto;
 use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
 use table_row;
 
 #[derive(Copy, Clone, RustcEncodable, Debug)]
 pub enum TableLayout {
     Fixed,
--- a/servo/components/layout/text.rs
+++ b/servo/components/layout/text.rs
@@ -20,18 +20,18 @@ use linked_list::split_off_head;
 use range::Range;
 use std::borrow::ToOwned;
 use std::collections::LinkedList;
 use std::mem;
 use std::sync::Arc;
 use style::computed_values::white_space;
 use style::computed_values::{line_height, text_orientation, text_rendering, text_transform};
 use style::logical_geometry::{LogicalSize, WritingMode};
-use style::properties::style_structs::ServoFont;
-use style::properties::{ComputedValues, ServoComputedValues};
+use style::properties::ServoComputedValues;
+use style::properties::style_structs;
 use unicode_bidi::{is_rtl, process_text};
 use unicode_script::{get_script, Script};
 
 /// Returns the concatenated text of a list of unscanned text fragments.
 fn text(fragments: &LinkedList<Fragment>) -> String {
     // FIXME: Some of this work is later duplicated in split_first_fragment_at_newline_if_necessary
     // and transform_text.  This code should be refactored so that the all the scanning for
     // newlines is done in a single pass.
@@ -426,21 +426,21 @@ fn bounding_box_for_run_metrics(metrics:
     // This will need to be updated when other text orientations are supported.
     LogicalSize::new(
         writing_mode,
         metrics.bounding_box.size.width,
         metrics.bounding_box.size.height)
 
 }
 
-/// Returns the metrics of the font represented by the given `ServoFont`, respectively.
+/// Returns the metrics of the font represented by the given `style_structs::Font`, respectively.
 ///
 /// `#[inline]` because often the caller only needs a few fields from the font metrics.
 #[inline]
-pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: Arc<ServoFont>)
+pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: Arc<style_structs::Font>)
                               -> FontMetrics {
     let fontgroup = font_context.layout_font_group_for_style(font_style);
     // FIXME(https://github.com/rust-lang/rust/issues/23338)
     let font = fontgroup.fonts[0].borrow();
     font.metrics.clone()
 }
 
 /// Returns the line block-size needed by the given computed style and font size.
--- a/servo/components/layout/traversal.rs
+++ b/servo/components/layout/traversal.rs
@@ -8,31 +8,30 @@ use construct::FlowConstructor;
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::DisplayListBuildState;
 use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal};
 use flow::{PreorderFlowTraversal, self};
 use gfx::display_list::OpaqueNode;
 use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
 use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
 use std::mem;
+use style::context::SharedStyleContext;
 use style::dom::TNode;
-use style::properties::ServoComputedValues;
 use style::selector_impl::ServoSelectorImpl;
-use style::servo::SharedStyleContext;
 use style::traversal::{DomTraversalContext, remove_from_bloom_filter, recalc_style_at};
 use util::opts;
 use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
 
 pub struct RecalcStyleAndConstructFlows<'lc> {
     context: LayoutContext<'lc>,
     root: OpaqueNode,
 }
 
 impl<'lc, N> DomTraversalContext<N> for RecalcStyleAndConstructFlows<'lc>
-    where N: LayoutNode + TNode<ConcreteComputedValues=ServoComputedValues>,
+    where N: LayoutNode + TNode,
           N::ConcreteElement: ::selectors::Element<Impl=ServoSelectorImpl, AttrString=String>
 
 {
     type SharedContext = SharedLayoutContext;
     #[allow(unsafe_code)]
     fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {
         // FIXME(bholley): This transmutation from &'a to &'lc is very unfortunate, but I haven't
         // found a way to avoid it despite spending several days on it (and consulting Manishearth,
--- a/servo/components/layout/wrapper.rs
+++ b/servo/components/layout/wrapper.rs
@@ -30,17 +30,16 @@
 
 #![allow(unsafe_code)]
 
 use core::nonzero::NonZero;
 use data::{LayoutDataFlags, PrivateLayoutData};
 use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
 use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
 use style::computed_values::content::{self, ContentItem};
-use style::properties::ComputedValues;
 use style::refcell::{Ref, RefCell, RefMut};
 
 pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>;
 
 pub trait LayoutNodeLayoutData {
     /// Similar to borrow_data*, but returns the full PrivateLayoutData rather
     /// than only the PrivateStyleData.
     unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData>;
--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -93,28 +93,28 @@ use script_traits::{ConstellationControl
 use script_traits::{StackingContextScrollState, UntrustedNodeAddress};
 use std::borrow::ToOwned;
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use std::ops::{Deref, DerefMut};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::sync::{Arc, Mutex, MutexGuard, RwLock};
+use style::animation::Animation;
 use style::computed_values::{filter, mix_blend_mode};
-use style::context::ReflowGoal;
+use style::context::{ReflowGoal, LocalStyleContextCreationInfo, SharedStyleContext};
 use style::dom::{TDocument, TElement, TNode};
 use style::error_reporting::ParseErrorReporter;
 use style::logical_geometry::LogicalPoint;
 use style::media_queries::{Device, MediaType};
 use style::parallel::WorkQueueData;
-use style::properties::ComputedValues;
 use style::refcell::RefCell;
-use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS;
-use style::servo::{Animation, LocalStyleContextCreationInfo, SharedStyleContext, Stylesheet, Stylist};
-use style::stylesheets::CSSRuleIteratorExt;
+use style::selector_matching::Stylist;
+use style::servo_selector_impl::USER_OR_USER_AGENT_STYLESHEETS;
+use style::stylesheets::{Stylesheet, CSSRuleIteratorExt};
 use style::workqueue::WorkQueue;
 use url::Url;
 use util::geometry::MAX_RECT;
 use util::ipc::OptionalIpcSender;
 use util::opts;
 use util::thread;
 use util::thread_state;
 
--- a/servo/components/script/dom/document.rs
+++ b/servo/components/script/dom/document.rs
@@ -118,18 +118,18 @@ use std::iter::once;
 use std::mem;
 use std::ptr;
 use std::rc::Rc;
 use std::sync::Arc;
 use string_cache::{Atom, QualName};
 use style::attr::AttrValue;
 use style::context::ReflowGoal;
 use style::restyle_hints::ElementSnapshot;
-use style::servo::Stylesheet;
 use style::str::{split_html_space_chars, str_join};
+use style::stylesheets::Stylesheet;
 use time;
 use url::Url;
 use url::percent_encoding::percent_decode;
 use util::prefs::PREFS;
 
 #[derive(JSTraceable, PartialEq, HeapSizeOf)]
 pub enum IsHTMLDocument {
     HTMLDocument,
--- a/servo/components/script/dom/htmllinkelement.rs
+++ b/servo/components/script/dom/htmllinkelement.rs
@@ -34,19 +34,18 @@ use std::borrow::ToOwned;
 use std::cell::Cell;
 use std::default::Default;
 use std::mem;
 use std::sync::{Arc, Mutex};
 use string_cache::Atom;
 use style::attr::AttrValue;
 use style::media_queries::{MediaQueryList, parse_media_query_list};
 use style::parser::ParserContextExtraData;
-use style::servo::Stylesheet;
 use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::Origin;
+use style::stylesheets::{Stylesheet, Origin};
 use url::Url;
 
 no_jsmanaged_fields!(Stylesheet);
 
 #[dom_struct]
 pub struct HTMLLinkElement {
     htmlelement: HTMLElement,
     rel_list: MutNullableHeap<JS<DOMTokenList>>,
--- a/servo/components/script/dom/htmlmetaelement.rs
+++ b/servo/components/script/dom/htmlmetaelement.rs
@@ -15,19 +15,18 @@ use dom::element::{AttributeMutation, El
 use dom::htmlelement::HTMLElement;
 use dom::htmlheadelement::HTMLHeadElement;
 use dom::node::{Node, UnbindContext, document_from_node};
 use dom::virtualmethods::VirtualMethods;
 use std::ascii::AsciiExt;
 use std::sync::Arc;
 use string_cache::Atom;
 use style::attr::AttrValue;
-use style::servo::Stylesheet;
 use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::{CSSRule, Origin};
+use style::stylesheets::{Stylesheet, CSSRule, Origin};
 use style::viewport::ViewportRule;
 
 #[dom_struct]
 pub struct HTMLMetaElement {
     htmlelement: HTMLElement,
     stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
 }
 
--- a/servo/components/script/dom/htmlstyleelement.rs
+++ b/servo/components/script/dom/htmlstyleelement.rs
@@ -14,18 +14,17 @@ use dom::element::Element;
 use dom::htmlelement::HTMLElement;
 use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node};
 use dom::virtualmethods::VirtualMethods;
 use script_layout_interface::message::Msg;
 use std::sync::Arc;
 use string_cache::Atom;
 use style::media_queries::parse_media_query_list;
 use style::parser::ParserContextExtraData;
-use style::servo::Stylesheet;
-use style::stylesheets::Origin;
+use style::stylesheets::{Stylesheet, Origin};
 
 #[dom_struct]
 pub struct HTMLStyleElement {
     htmlelement: HTMLElement,
     stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
 }
 
 impl HTMLStyleElement {
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -49,24 +49,24 @@ use script_layout_interface::{HTMLCanvas
 use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
 use selectors::matching::{DeclarationBlock, ElementFlags};
 use selectors::parser::{AttrSelector, NamespaceConstraint};
 use std::marker::PhantomData;
 use std::mem::{transmute, transmute_copy};
 use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
 use style::attr::AttrValue;
 use style::computed_values::display;
+use style::context::SharedStyleContext;
+use style::data::PrivateStyleData;
 use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode};
 use style::element_state::*;
-use style::properties::{ComputedValues, ServoComputedValues};
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
 use style::refcell::{Ref, RefCell, RefMut};
 use style::restyle_hints::ElementSnapshot;
 use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
-use style::servo::{PrivateStyleData, SharedStyleContext};
 use style::sink::Push;
 use style::str::is_whitespace;
 use url::Url;
 
 #[derive(Copy, Clone)]
 pub struct ServoLayoutNode<'a> {
     /// The wrapped node.
     node: LayoutJS<Node>,
@@ -105,17 +105,16 @@ impl<'ln> ServoLayoutNode<'ln> {
     fn script_type_id(&self) -> NodeTypeId {
         unsafe {
             self.node.type_id_for_layout()
         }
     }
 }
 
 impl<'ln> TNode for ServoLayoutNode<'ln> {
-    type ConcreteComputedValues = ServoComputedValues;
     type ConcreteElement = ServoLayoutElement<'ln>;
     type ConcreteDocument = ServoLayoutDocument<'ln>;
     type ConcreteRestyleDamage = RestyleDamage;
 
     fn to_unsafe(&self) -> UnsafeNode {
         unsafe {
             let ptr: usize = transmute_copy(self);
             (ptr, 0)
--- a/servo/components/script_layout_interface/lib.rs
+++ b/servo/components/script_layout_interface/lib.rs
@@ -47,18 +47,18 @@ pub mod restyle_damage;
 pub mod rpc;
 pub mod wrapper_traits;
 
 use canvas_traits::CanvasMsg;
 use core::nonzero::NonZero;
 use ipc_channel::ipc::IpcSender;
 use libc::c_void;
 use restyle_damage::RestyleDamage;
+use style::data::PrivateStyleData;
 use style::refcell::RefCell;
-use style::servo::PrivateStyleData;
 
 pub struct PartialStyleAndLayoutData {
     pub style_data: PrivateStyleData,
     pub restyle_damage: RestyleDamage,
 }
 
 #[derive(Copy, Clone, HeapSizeOf)]
 pub struct OpaqueStyleAndLayoutData {
--- a/servo/components/script_layout_interface/message.rs
+++ b/servo/components/script_layout_interface/message.rs
@@ -13,17 +13,17 @@ use profile_traits::mem::ReportsChan;
 use rpc::LayoutRPC;
 use script_traits::{ConstellationControlMsg, LayoutControlMsg};
 use script_traits::{LayoutMsg as ConstellationMsg, StackingContextScrollState, WindowSizeData};
 use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender};
 use string_cache::Atom;
 use style::context::ReflowGoal;
 use style::selector_impl::PseudoElement;
-use style::servo::Stylesheet;
+use style::stylesheets::Stylesheet;
 use url::Url;
 use util::ipc::OptionalOpaqueIpcSender;
 use {OpaqueStyleAndLayoutData, TrustedNodeAddress};
 
 /// Asynchronous messages that script can send to layout.
 pub enum Msg {
     /// Adds the given stylesheet to the document.
     AddStylesheet(Arc<Stylesheet>),
--- a/servo/components/script_layout_interface/restyle_damage.rs
+++ b/servo/components/script_layout_interface/restyle_damage.rs
@@ -1,17 +1,17 @@
 /* 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 std::fmt;
 use std::sync::Arc;
 use style::computed_values::display;
 use style::dom::TRestyleDamage;
-use style::properties::{ComputedValues, ServoComputedValues};
+use style::properties::ServoComputedValues;
 
 bitflags! {
     #[doc = "Individual layout actions that may be necessary after restyling."]
     pub flags RestyleDamage: u8 {
         #[doc = "Repaint the node itself."]
         #[doc = "Currently unused; need to decide how this propagates."]
         const REPAINT = 0x01,
 
@@ -39,17 +39,16 @@ bitflags! {
         const RESOLVE_GENERATED_CONTENT = 0x20,
 
         #[doc = "The entire flow needs to be reconstructed."]
         const RECONSTRUCT_FLOW = 0x40
     }
 }
 
 impl TRestyleDamage for RestyleDamage {
-    type ConcreteComputedValues = ServoComputedValues;
     fn compute(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) ->
         RestyleDamage { compute_damage(old, new) }
 
     /// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
     ///
     /// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
     /// unnecessary sequential resolution of generated content.
     fn rebuild_and_reflow() -> RestyleDamage {
--- a/servo/components/script_layout_interface/wrapper_traits.rs
+++ b/servo/components/script_layout_interface/wrapper_traits.rs
@@ -8,22 +8,22 @@ use OpaqueStyleAndLayoutData;
 use PartialStyleAndLayoutData;
 use gfx_traits::{ByteIndex, LayerId, LayerType};
 use msg::constellation_msg::PipelineId;
 use range::Range;
 use restyle_damage::RestyleDamage;
 use std::sync::Arc;
 use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
 use style::computed_values::display;
+use style::context::SharedStyleContext;
 use style::dom::OpaqueNode;
 use style::dom::{PresentationalHintsSynthetizer, TNode};
 use style::properties::ServoComputedValues;
 use style::refcell::{Ref, RefCell};
 use style::selector_impl::{PseudoElement, PseudoElementCascadeType, ServoSelectorImpl};
-use style::servo::SharedStyleContext;
 use url::Url;
 
 #[derive(Copy, PartialEq, Clone)]
 pub enum PseudoElementType<T> {
     Normal,
     Before(T),
     After(T),
     DetailsSummary(T),
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -10,19 +10,17 @@ use dom::{OpaqueNode, TRestyleDamage};
 use euclid::point::Point2D;
 use keyframes::{KeyframesStep, KeyframesStepValue};
 use properties::animated_properties::{AnimatedProperty, TransitionProperty};
 use properties::longhands::animation_direction::computed_value::AnimationDirection;
 use properties::longhands::animation_iteration_count::computed_value::AnimationIterationCount;
 use properties::longhands::animation_play_state::computed_value::AnimationPlayState;
 use properties::longhands::transition_timing_function::computed_value::StartEnd;
 use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction;
-use properties::style_struct_traits::Box;
 use properties::{self, ComputedValues};
-use selector_impl::SelectorImplExt;
 use selectors::matching::DeclarationBlock;
 use std::sync::Arc;
 use std::sync::mpsc::Sender;
 use string_cache::Atom;
 use time;
 use values::computed::Time;
 
 /// This structure represents a keyframes animation current iteration state.
@@ -48,17 +46,17 @@ pub enum KeyframesRunningState {
     Running,
 }
 
 /// This structure represents the current keyframe animation state, i.e., the
 /// duration, the current and maximum iteration count, and the state (either
 /// playing or paused).
 // TODO: unify the use of f32/f64 in this file.
 #[derive(Debug, Clone)]
-pub struct KeyframesAnimationState<Impl: SelectorImplExt> {
+pub struct KeyframesAnimationState {
     /// The time this animation started at.
     pub started_at: f64,
     /// The duration of this animation.
     pub duration: f64,
     /// The delay of the animation.
     pub delay: f64,
     /// The current iteration state for the animation.
     pub iteration_state: KeyframesIterationState,
@@ -67,20 +65,20 @@ pub struct KeyframesAnimationState<Impl:
     /// The declared animation direction of this animation.
     pub direction: AnimationDirection,
     /// The current animation direction. This can only be `normal` or `reverse`.
     pub current_direction: AnimationDirection,
     /// Werther this keyframe animation is outdated due to a restyle.
     pub expired: bool,
     /// The original cascade style, needed to compute the generated keyframes of
     /// the animation.
-    pub cascade_style: Arc<Impl::ComputedValues>,
+    pub cascade_style: Arc<ComputedValues>,
 }
 
-impl<Impl: SelectorImplExt> KeyframesAnimationState<Impl> {
+impl KeyframesAnimationState {
     /// Performs a tick in the animation state, i.e., increments the counter of
     /// the current iteration count, updates times and then toggles the
     /// direction if appropriate.
     ///
     /// Returns true if the animation should keep running.
     pub fn tick(&mut self) -> bool {
         debug!("KeyframesAnimationState::tick");
         debug_assert!(!self.expired);
@@ -175,29 +173,29 @@ impl<Impl: SelectorImplExt> KeyframesAni
             KeyframesRunningState::Paused(..) => true,
             KeyframesRunningState::Running => false,
         }
     }
 }
 
 /// State relating to an animation.
 #[derive(Clone, Debug)]
-pub enum Animation<Impl: SelectorImplExt> {
+pub enum Animation {
     /// A transition is just a single frame triggered at a time, with a reflow.
     ///
     /// the f64 field is the start time as returned by `time::precise_time_s()`.
     ///
     /// The `bool` field is werther this animation should no longer run.
     Transition(OpaqueNode, f64, AnimationFrame, bool),
     /// A keyframes animation is identified by a name, and can have a
     /// node-dependent state (i.e. iteration count, etc.).
-    Keyframes(OpaqueNode, Atom, KeyframesAnimationState<Impl>),
+    Keyframes(OpaqueNode, Atom, KeyframesAnimationState),
 }
 
-impl<Impl: SelectorImplExt> Animation<Impl> {
+impl Animation {
     #[inline]
     pub fn mark_as_expired(&mut self) {
         debug_assert!(!self.is_expired());
         match *self {
             Animation::Transition(_, _, _, ref mut expired) => *expired = true,
             Animation::Keyframes(_, _, ref mut state) => state.expired = true,
         }
     }
@@ -244,20 +242,20 @@ pub struct PropertyAnimation {
     timing_function: TransitionTimingFunction,
     duration: Time, // TODO: isn't this just repeated?
 }
 
 impl PropertyAnimation {
     /// Creates a new property animation for the given transition index and old and new styles.
     /// Any number of animations may be returned, from zero (if the property did not animate) to
     /// one (for a single transition property) to arbitrarily many (for `all`).
-    pub fn from_transition<C: ComputedValues>(transition_index: usize,
-                                              old_style: &C,
-                                              new_style: &mut C)
-                                              -> Vec<PropertyAnimation> {
+    pub fn from_transition(transition_index: usize,
+                           old_style: &ComputedValues,
+                           new_style: &mut ComputedValues)
+                           -> Vec<PropertyAnimation> {
         let mut result = vec![];
         let box_style = new_style.get_box();
         let transition_property = box_style.transition_property_at(transition_index);
         let timing_function = box_style.transition_timing_function_mod(transition_index);
         let duration = box_style.transition_duration_mod(transition_index);
 
 
         if transition_property != TransitionProperty::All {
@@ -281,22 +279,22 @@ impl PropertyAnimation {
                                                                 new_style) {
                 result.push(property_animation)
             }
         });
 
         result
     }
 
-    fn from_transition_property<C: ComputedValues>(transition_property: TransitionProperty,
-                                                   timing_function: TransitionTimingFunction,
-                                                   duration: Time,
-                                                   old_style: &C,
-                                                   new_style: &C)
-                                                   -> Option<PropertyAnimation> {
+    fn from_transition_property(transition_property: TransitionProperty,
+                                timing_function: TransitionTimingFunction,
+                                duration: Time,
+                                old_style: &ComputedValues,
+                                new_style: &ComputedValues)
+                                -> Option<PropertyAnimation> {
         let animated_property = AnimatedProperty::from_transition_property(&transition_property,
                                                                            old_style,
                                                                            new_style);
 
         let property_animation = PropertyAnimation {
             property: animated_property,
             timing_function: timing_function,
             duration: duration,
@@ -304,17 +302,17 @@ impl PropertyAnimation {
 
         if property_animation.does_animate() {
             Some(property_animation)
         } else {
             None
         }
     }
 
-    pub fn update<C: ComputedValues>(&self, style: &mut C, time: f64) {
+    pub fn update(&self, style: &mut ComputedValues, time: f64) {
         let progress = match self.timing_function {
             TransitionTimingFunction::CubicBezier(p1, p2) => {
                 // See `WebCore::AnimationBase::solveEpsilon(double)` in WebKit.
                 let epsilon = 1.0 / (200.0 * (self.duration.seconds() as f64));
                 Bezier::new(Point2D::new(p1.x as f64, p1.y as f64),
                             Point2D::new(p2.x as f64, p2.y as f64)).solve(time, epsilon)
             }
             TransitionTimingFunction::Steps(steps, StartEnd::Start) => {
@@ -335,21 +333,21 @@ impl PropertyAnimation {
 }
 
 /// Inserts transitions into the queue of running animations as applicable for
 /// the given style difference. This is called from the layout worker threads.
 /// Returns true if any animations were kicked off and false otherwise.
 //
 // TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
 // cloneable part and a non-cloneable part..
-pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sender: &Sender<Animation<Impl>>,
-                                                              node: OpaqueNode,
-                                                              old_style: &Impl::ComputedValues,
-                                                              new_style: &mut Arc<Impl::ComputedValues>)
-                                                              -> bool {
+pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
+                                       node: OpaqueNode,
+                                       old_style: &ComputedValues,
+                                       new_style: &mut Arc<ComputedValues>)
+                                       -> bool {
     let mut had_animations = false;
     for i in 0..new_style.get_box().transition_property_count() {
         // Create any property animations, if applicable.
         let property_animations = PropertyAnimation::from_transition(i, old_style, Arc::make_mut(new_style));
         for property_animation in property_animations {
             // Set the property to the initial value.
             // NB: get_mut is guaranteed to succeed since we called make_mut()
             // above.
@@ -368,21 +366,21 @@ pub fn start_transitions_if_applicable<I
 
             had_animations = true;
         }
     }
 
     had_animations
 }
 
-fn compute_style_for_animation_step<Impl: SelectorImplExt>(context: &SharedStyleContext<Impl>,
-                                                           step: &KeyframesStep,
-                                                           previous_style: &Impl::ComputedValues,
-                                                           style_from_cascade: &Impl::ComputedValues)
-                                                           -> Impl::ComputedValues {
+fn compute_style_for_animation_step(context: &SharedStyleContext,
+                                    step: &KeyframesStep,
+                                    previous_style: &ComputedValues,
+                                    style_from_cascade: &ComputedValues)
+                                    -> ComputedValues {
     match step.value {
         // TODO: avoiding this spurious clone might involve having to create
         // an Arc in the below (more common case).
         KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
         KeyframesStepValue::Declarations(ref declarations) => {
             let declaration_block = DeclarationBlock {
                 declarations: declarations.clone(),
                 source_order: 0,
@@ -394,21 +392,21 @@ fn compute_style_for_animation_step<Impl
                                                     Some(previous_style),
                                                     None,
                                                     context.error_reporter.clone());
             computed
         }
     }
 }
 
-pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContext<Impl>,
-                                                     new_animations_sender: &Sender<Animation<Impl>>,
-                                                     node: OpaqueNode,
-                                                     new_style: &Arc<Impl::ComputedValues>) -> bool
-{
+pub fn maybe_start_animations(context: &SharedStyleContext,
+                              new_animations_sender: &Sender<Animation>,
+                              node: OpaqueNode,
+                              new_style: &Arc<ComputedValues>)
+                              -> bool {
     let mut had_animations = false;
 
     let box_style = new_style.get_box();
     for (i, name) in box_style.animation_name_iter().enumerate() {
         debug!("maybe_start_animations: name={}", name);
         let total_duration = box_style.animation_duration_mod(i).seconds();
         if total_duration == 0. {
             continue
@@ -465,41 +463,40 @@ pub fn maybe_start_animations<Impl: Sele
         }
     }
 
     had_animations
 }
 
 /// Updates a given computed style for a given animation frame. Returns a bool
 /// representing if the style was indeed updated.
-pub fn update_style_for_animation_frame<C: ComputedValues>(mut new_style: &mut Arc<C>,
-                                                           now: f64,
-                                                           start_time: f64,
-                                                           frame: &AnimationFrame) -> bool {
+pub fn update_style_for_animation_frame(mut new_style: &mut Arc<ComputedValues>,
+                                        now: f64,
+                                        start_time: f64,
+                                        frame: &AnimationFrame) -> bool {
     let mut progress = (now - start_time) / frame.duration;
     if progress > 1.0 {
         progress = 1.0
     }
 
     if progress <= 0.0 {
         return false;
     }
 
     frame.property_animation.update(Arc::make_mut(&mut new_style), progress);
 
     true
 }
 /// Updates a single animation and associated style based on the current time.
 /// If `damage` is provided, inserts the appropriate restyle damage.
-pub fn update_style_for_animation<Damage, Impl>(context: &SharedStyleContext<Impl>,
-                                                animation: &Animation<Impl>,
-                                                style: &mut Arc<Damage::ConcreteComputedValues>,
-                                                damage: Option<&mut Damage>)
-where Impl: SelectorImplExt,
-      Damage: TRestyleDamage<ConcreteComputedValues = Impl::ComputedValues> {
+pub fn update_style_for_animation<Damage>(context: &SharedStyleContext,
+                                          animation: &Animation,
+                                          style: &mut Arc<ComputedValues>,
+                                          damage: Option<&mut Damage>)
+where Damage: TRestyleDamage {
     debug!("update_style_for_animation: entering");
     debug_assert!(!animation.is_expired());
     match *animation {
         Animation::Transition(_, start_time, ref frame, _) => {
             debug!("update_style_for_animation: transition found");
             let now = time::precise_time_s();
             let mut new_style = (*style).clone();
             let updated_style = update_style_for_animation_frame(&mut new_style,
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -5,87 +5,86 @@
 //! The context within which style is calculated.
 
 use animation::Animation;
 use app_units::Au;
 use dom::OpaqueNode;
 use error_reporting::ParseErrorReporter;
 use euclid::Size2D;
 use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
-use selector_impl::SelectorImplExt;
 use selector_matching::Stylist;
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::sync::mpsc::Sender;
 use std::sync::{Arc, Mutex, RwLock};
 
 /// This structure is used to create a local style context from a shared one.
-pub struct LocalStyleContextCreationInfo<Impl: SelectorImplExt> {
-    new_animations_sender: Sender<Animation<Impl>>,
+pub struct LocalStyleContextCreationInfo {
+    new_animations_sender: Sender<Animation>,
 }
 
-impl<Impl: SelectorImplExt> LocalStyleContextCreationInfo<Impl> {
-    pub fn new(animations_sender: Sender<Animation<Impl>>) -> Self {
+impl LocalStyleContextCreationInfo {
+    pub fn new(animations_sender: Sender<Animation>) -> Self {
         LocalStyleContextCreationInfo {
             new_animations_sender: animations_sender,
         }
     }
 }
 
-pub struct SharedStyleContext<Impl: SelectorImplExt> {
+pub struct SharedStyleContext {
     /// The current viewport size.
     pub viewport_size: Size2D<Au>,
 
     /// Screen sized changed?
     pub screen_size_changed: bool,
 
     /// The CSS selector stylist.
-    pub stylist: Arc<Stylist<Impl>>,
+    pub stylist: Arc<Stylist>,
 
     /// Starts at zero, and increased by one every time a layout completes.
     /// This can be used to easily check for invalid stale data.
     pub generation: u32,
 
     /// Why is this reflow occurring
     pub goal: ReflowGoal,
 
     /// The animations that are currently running.
-    pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation<Impl>>>>>,
+    pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
 
     /// The list of animations that have expired since the last style recalculation.
-    pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation<Impl>>>>>,
+    pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
 
     ///The CSS error reporter for all CSS loaded in this layout thread
     pub error_reporter: Box<ParseErrorReporter + Sync>,
 
     /// Data needed to create the local style context from the shared one.
-    pub local_context_creation_data: Mutex<LocalStyleContextCreationInfo<Impl>>,
+    pub local_context_creation_data: Mutex<LocalStyleContextCreationInfo>,
 }
 
-pub struct LocalStyleContext<Impl: SelectorImplExt> {
-    pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache<Impl::ComputedValues>>,
-    pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache<Impl::ComputedValues>>,
+pub struct LocalStyleContext {
+    pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache>,
+    pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
     /// A channel on which new animations that have been triggered by style
     /// recalculation can be sent.
-    pub new_animations_sender: Sender<Animation<Impl>>,
+    pub new_animations_sender: Sender<Animation>,
 }
 
-impl<Impl: SelectorImplExt> LocalStyleContext<Impl> {
-    pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo<Impl>) -> Self {
+impl LocalStyleContext {
+    pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo) -> Self {
         LocalStyleContext {
             applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
             style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
             new_animations_sender: local_context_creation_data.new_animations_sender.clone(),
         }
     }
 }
 
-pub trait StyleContext<'a, Impl: SelectorImplExt> {
-    fn shared_context(&self) -> &'a SharedStyleContext<Impl>;
-    fn local_context(&self) -> &LocalStyleContext<Impl>;
+pub trait StyleContext<'a> {
+    fn shared_context(&self) -> &'a SharedStyleContext;
+    fn local_context(&self) -> &LocalStyleContext;
 }
 
 /// Why we're doing reflow.
 #[derive(PartialEq, Copy, Clone, Debug)]
 pub enum ReflowGoal {
     /// We're reflowing in order to send a display list to the screen.
     ForDisplay,
     /// We're reflowing in order to satisfy a script query. No display list will be created.
--- a/servo/components/style/data.rs
+++ b/servo/components/style/data.rs
@@ -1,36 +1,35 @@
 /* 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/. */
 
 //! Per-node data used in style calculation.
 
 use properties::ComputedValues;
-use selectors::parser::SelectorImpl;
+use selector_impl::PseudoElement;
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use std::sync::Arc;
 use std::sync::atomic::AtomicIsize;
 
-pub struct PrivateStyleData<Impl: SelectorImpl, ConcreteComputedValues: ComputedValues> {
+pub struct PrivateStyleData {
     /// The results of CSS styling for this node.
-    pub style: Option<Arc<ConcreteComputedValues>>,
+    pub style: Option<Arc<ComputedValues>>,
 
     /// The results of CSS styling for each pseudo-element (if any).
-    pub per_pseudo: HashMap<Impl::PseudoElement, Arc<ConcreteComputedValues>,
+    pub per_pseudo: HashMap<PseudoElement, Arc<ComputedValues>,
                             BuildHasherDefault<::fnv::FnvHasher>>,
 
     /// Information needed during parallel traversals.
     pub parallel: DomParallelInfo,
 }
 
-impl<Impl, ConcreteComputedValues> PrivateStyleData<Impl, ConcreteComputedValues>
-    where Impl: SelectorImpl, ConcreteComputedValues: ComputedValues {
-    pub fn new() -> PrivateStyleData<Impl, ConcreteComputedValues> {
+impl PrivateStyleData {
+    pub fn new() -> Self {
         PrivateStyleData {
             style: None,
             per_pseudo: HashMap::with_hasher(Default::default()),
             parallel: DomParallelInfo::new(),
         }
     }
 }
 
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -41,26 +41,24 @@ impl OpaqueNode {
     /// Returns the address of this node, for debugging purposes.
     #[inline]
     pub fn id(&self) -> usize {
         self.0
     }
 }
 
 pub trait TRestyleDamage : BitOr<Output=Self> + Copy {
-    type ConcreteComputedValues: ComputedValues;
-    fn compute(old: Option<&Arc<Self::ConcreteComputedValues>>, new: &Self::ConcreteComputedValues) -> Self;
+    fn compute(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -> Self;
     fn rebuild_and_reflow() -> Self;
 }
 
 pub trait TNode : Sized + Copy + Clone {
     type ConcreteElement: TElement<ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>;
     type ConcreteDocument: TDocument<ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>;
-    type ConcreteRestyleDamage: TRestyleDamage<ConcreteComputedValues = Self::ConcreteComputedValues>;
-    type ConcreteComputedValues: ComputedValues;
+    type ConcreteRestyleDamage: TRestyleDamage;
 
     fn to_unsafe(&self) -> UnsafeNode;
     unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
 
     /// Returns whether this is a text node. It turns out that this is all the style system cares
     /// about, and thus obviates the need to compute the full type id, which would be expensive in
     /// Gecko.
     fn is_text_node(&self) -> bool;
@@ -141,31 +139,25 @@ pub trait TNode : Sized + Copy + Clone {
     }
 
     fn can_be_fragmented(&self) -> bool;
 
     unsafe fn set_can_be_fragmented(&self, value: bool);
 
     /// Borrows the PrivateStyleData without checks.
     #[inline(always)]
-    unsafe fn borrow_data_unchecked(&self)
-        -> Option<*const PrivateStyleData<<Self::ConcreteElement as Element>::Impl,
-                                           Self::ConcreteComputedValues>>;
+    unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData>;
 
     /// Borrows the PrivateStyleData immutably. Fails on a conflicting borrow.
     #[inline(always)]
-    fn borrow_data(&self)
-        -> Option<Ref<PrivateStyleData<<Self::ConcreteElement as Element>::Impl,
-                                           Self::ConcreteComputedValues>>>;
+    fn borrow_data(&self) -> Option<Ref<PrivateStyleData>>;
 
     /// Borrows the PrivateStyleData mutably. Fails on a conflicting borrow.
     #[inline(always)]
-    fn mutate_data(&self)
-        -> Option<RefMut<PrivateStyleData<<Self::ConcreteElement as Element>::Impl,
-                                           Self::ConcreteComputedValues>>>;
+    fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
 
     /// Get the description of how to account for recent style changes.
     fn restyle_damage(self) -> Self::ConcreteRestyleDamage;
 
     /// Set the restyle damage field.
     fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage);
 
     fn parent_node(&self) -> Option<Self>;
@@ -176,20 +168,18 @@ pub trait TNode : Sized + Copy + Clone {
 
     fn prev_sibling(&self) -> Option<Self>;
 
     fn next_sibling(&self) -> Option<Self>;
 
 
     /// Returns the style results for the given node. If CSS selector matching
     /// has not yet been performed, fails.
-    fn style(&self,
-             _context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>)
-        -> Ref<Arc<Self::ConcreteComputedValues>>
-        where <Self::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues=Self::ConcreteComputedValues> {
+    fn style(&self, _context: &SharedStyleContext) -> Ref<Arc<ComputedValues>>
+        where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
         Ref::map(self.borrow_data().unwrap(), |data| data.style.as_ref().unwrap())
     }
 
     /// Removes the style from this node.
     fn unstyle(self) {
         self.mutate_data().unwrap().style = None;
     }
 }
new file mode 100644
--- /dev/null
+++ b/servo/components/style/gecko_glue.rs
@@ -0,0 +1,57 @@
+/* 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/. */
+
+#![allow(unsafe_code)]
+
+use std::marker::PhantomData;
+use std::mem::{forget, transmute};
+use std::sync::Arc;
+
+pub struct ArcHelpers<GeckoType, ServoType> {
+    phantom1: PhantomData<GeckoType>,
+    phantom2: PhantomData<ServoType>,
+}
+
+
+impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
+    pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
+                           where F: FnOnce(&Arc<ServoType>) -> Output {
+        debug_assert!(!raw.is_null());
+
+        let owned = unsafe { Self::into(raw) };
+        let result = cb(&owned);
+        forget(owned);
+        result
+    }
+
+    pub fn maybe_with<F, Output>(maybe_raw: *mut GeckoType, cb: F) -> Output
+                                 where F: FnOnce(Option<&Arc<ServoType>>) -> Output {
+        let owned = if maybe_raw.is_null() {
+            None
+        } else {
+            Some(unsafe { Self::into(maybe_raw) })
+        };
+
+        let result = cb(owned.as_ref());
+        forget(owned);
+
+        result
+    }
+
+    pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
+        transmute(ptr)
+    }
+
+    pub fn from(owned: Arc<ServoType>) -> *mut GeckoType {
+        unsafe { transmute(owned) }
+    }
+
+    pub unsafe fn addref(ptr: *mut GeckoType) {
+        Self::with(ptr, |arc| forget(arc.clone()));
+    }
+
+    pub unsafe fn release(ptr: *mut GeckoType) {
+        let _ = Self::into(ptr);
+    }
+}
rename from servo/ports/geckolib/selector_impl.rs
rename to servo/components/style/gecko_selector_impl.rs
--- a/servo/ports/geckolib/selector_impl.rs
+++ b/servo/components/style/gecko_selector_impl.rs
@@ -1,26 +1,19 @@
 /* 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 properties::GeckoComputedValues;
+use element_state::ElementState;
+use selector_impl::{PseudoElementCascadeType, SelectorImplExt};
 use selectors::parser::{ParserContext, SelectorImpl};
 use string_cache::Atom;
-use style;
-use style::element_state::ElementState;
-use style::selector_impl::{PseudoElementCascadeType, SelectorImplExt};
+use stylesheets::Stylesheet;
 
-pub type Stylist = style::selector_matching::Stylist<GeckoSelectorImpl>;
-pub type Stylesheet = style::stylesheets::Stylesheet<GeckoSelectorImpl>;
-pub type SharedStyleContext = style::context::SharedStyleContext<GeckoSelectorImpl>;
-pub type PrivateStyleData = style::data::PrivateStyleData<GeckoSelectorImpl, GeckoComputedValues>;
-pub type Animation = style::animation::Animation<GeckoSelectorImpl>;
-
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct GeckoSelectorImpl;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum PseudoElement {
     Before,
     After,
 
     Backdrop,
@@ -130,18 +123,18 @@ pub enum NonTSPseudoClass {
     Checked,
     Indeterminate,
     ReadWrite,
     ReadOnly,
 }
 
 impl NonTSPseudoClass {
     pub fn state_flag(&self) -> ElementState {
+        use element_state::*;
         use self::NonTSPseudoClass::*;
-        use style::element_state::*;
         match *self {
             Active => IN_ACTIVE_STATE,
             Focus => IN_FOCUS_STATE,
             Hover => IN_HOVER_STATE,
             Enabled => IN_ENABLED_STATE,
             Disabled => IN_DISABLED_STATE,
             Checked => IN_CHECKED_STATE,
             Indeterminate => IN_INDETERMINATE_STATE,
@@ -287,18 +280,16 @@ impl SelectorImpl for GeckoSelectorImpl 
             "-moz-svg-text" => MozSVGText,
 
             _ => return Err(())
         }))
     }
 }
 
 impl SelectorImplExt for GeckoSelectorImpl {
-    type ComputedValues = GeckoComputedValues;
-
     #[inline]
     fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
         match *pseudo {
             PseudoElement::Before |
             PseudoElement::After => PseudoElementCascadeType::Eager,
             PseudoElement::AnonBox(_) => PseudoElementCascadeType::Precomputed,
             _ => PseudoElementCascadeType::Lazy,
         }
rename from servo/ports/geckolib/values.rs
rename to servo/components/style/gecko_values.rs
--- a/servo/ports/geckolib/values.rs
+++ b/servo/components/style/gecko_values.rs
@@ -1,18 +1,20 @@
 /* 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/. */
 
+#![allow(unsafe_code)]
+
 use app_units::Au;
 use cssparser::RGBA;
 use gecko_bindings::structs::{nsStyleCoord, nsStyleUnion, nsStyleUnit};
 use std::cmp::max;
-use style::values::computed::Angle;
-use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
+use values::computed::Angle;
+use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 
 pub trait StyleCoordHelpers {
     fn copy_from(&mut self, other: &Self);
     fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T);
 
     fn set_auto(&mut self);
     fn is_auto(&self) -> bool;
 
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -76,30 +76,32 @@ pub mod bezier;
 pub mod cache;
 pub mod context;
 pub mod custom_properties;
 pub mod data;
 pub mod dom;
 pub mod element_state;
 pub mod error_reporting;
 pub mod font_face;
-#[cfg(feature = "gecko")]
-pub mod gecko_conversions;
+#[cfg(feature = "gecko")] pub mod gecko_conversions;
+#[cfg(feature = "gecko")] pub mod gecko_glue;
+#[cfg(feature = "gecko")] pub mod gecko_selector_impl;
+#[cfg(feature = "gecko")] pub mod gecko_values;
 pub mod keyframes;
 pub mod logical_geometry;
 pub mod matching;
 pub mod media_queries;
 pub mod parallel;
 pub mod parser;
 pub mod refcell;
 pub mod restyle_hints;
 pub mod selector_impl;
 pub mod selector_matching;
 pub mod sequential;
-pub mod servo;
+#[cfg(feature = "servo")] pub mod servo_selector_impl;
 pub mod sink;
 pub mod str;
 pub mod stylesheets;
 mod tid;
 pub mod traversal;
 #[macro_use]
 #[allow(non_camel_case_types)]
 pub mod values;
@@ -111,16 +113,22 @@ use std::sync::Arc;
 /// The CSS properties supported by the style system.
 // Generated from the properties.mako.rs template by build.rs
 #[macro_use]
 #[allow(unsafe_code)]
 pub mod properties {
     include!(concat!(env!("OUT_DIR"), "/properties.rs"));
 }
 
+#[cfg(feature = "gecko")]
+#[allow(unsafe_code)]
+pub mod gecko_properties {
+    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
+}
+
 macro_rules! reexport_computed_values {
     ( $( $name: ident )+ ) => {
         /// Types for [computed values][computed].
         ///
         /// [computed]: https://drafts.csswg.org/css-cascade/#computed
         pub mod computed_values {
             $(
                 pub use properties::longhands::$name::computed_value as $name;
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -8,17 +8,17 @@
 
 use animation::{self, Animation};
 use arc_ptr_eq;
 use cache::{LRUCache, SimpleHashCache};
 use context::{StyleContext, SharedStyleContext};
 use data::PrivateStyleData;
 use dom::{TElement, TNode, TRestyleDamage};
 use properties::{ComputedValues, PropertyDeclaration, cascade};
-use selector_impl::{ElementExt, SelectorImplExt};
+use selector_impl::{ElementExt, SelectorImplExt, TheSelectorImpl, PseudoElement};
 use selector_matching::{DeclarationBlock, Stylist};
 use selectors::Element;
 use selectors::bloom::BloomFilter;
 use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
 use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
 use sink::ForgetfulSink;
 use smallvec::SmallVec;
 use std::collections::HashMap;
@@ -43,35 +43,35 @@ fn create_common_style_affecting_attribu
                     flags.insert(flag)
                 }
             }
         }
     }
     flags
 }
 
-pub struct ApplicableDeclarations<Impl: SelectorImplExt> {
+pub struct ApplicableDeclarations {
     pub normal: SmallVec<[DeclarationBlock; 16]>,
-    pub per_pseudo: HashMap<Impl::PseudoElement,
+    pub per_pseudo: HashMap<PseudoElement,
                             Vec<DeclarationBlock>,
                             BuildHasherDefault<::fnv::FnvHasher>>,
 
     /// Whether the `normal` declarations are shareable with other nodes.
     pub normal_shareable: bool,
 }
 
-impl<Impl: SelectorImplExt> ApplicableDeclarations<Impl> {
-    pub fn new() -> ApplicableDeclarations<Impl> {
+impl ApplicableDeclarations {
+    pub fn new() -> Self {
         let mut applicable_declarations = ApplicableDeclarations {
             normal: SmallVec::new(),
             per_pseudo: HashMap::with_hasher(Default::default()),
             normal_shareable: false,
         };
 
-        Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
+        TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
             applicable_declarations.per_pseudo.insert(pseudo, vec![]);
         });
 
         applicable_declarations
     }
 }
 
 #[derive(Clone)]
@@ -144,77 +144,77 @@ impl<'a> Hash for ApplicableDeclarations
             let ptr = &*declaration.declarations as *const Vec<PropertyDeclaration>;
             ptr.hash(state);
         }
     }
 }
 
 static APPLICABLE_DECLARATIONS_CACHE_SIZE: usize = 32;
 
-pub struct ApplicableDeclarationsCache<C: ComputedValues> {
-    cache: SimpleHashCache<ApplicableDeclarationsCacheEntry, Arc<C>>,
+pub struct ApplicableDeclarationsCache {
+    cache: SimpleHashCache<ApplicableDeclarationsCacheEntry, Arc<ComputedValues>>,
 }
 
-impl<C: ComputedValues> ApplicableDeclarationsCache<C> {
+impl ApplicableDeclarationsCache {
     pub fn new() -> Self {
         ApplicableDeclarationsCache {
             cache: SimpleHashCache::new(APPLICABLE_DECLARATIONS_CACHE_SIZE),
         }
     }
 
-    pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<C>> {
+    pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> {
         match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) {
             None => None,
             Some(ref values) => Some((*values).clone()),
         }
     }
 
-    pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<C>) {
+    pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) {
         self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style)
     }
 
     pub fn evict_all(&mut self) {
         self.cache.evict_all();
     }
 }
 
 /// An LRU cache of the last few nodes seen, so that we can aggressively try to reuse their styles.
-pub struct StyleSharingCandidateCache<C: ComputedValues> {
-    cache: LRUCache<StyleSharingCandidate<C>, ()>,
+pub struct StyleSharingCandidateCache {
+    cache: LRUCache<StyleSharingCandidate, ()>,
 }
 
 #[derive(Clone)]
-pub struct StyleSharingCandidate<C: ComputedValues> {
-    pub style: Arc<C>,
-    pub parent_style: Arc<C>,
+pub struct StyleSharingCandidate {
+    pub style: Arc<ComputedValues>,
+    pub parent_style: Arc<ComputedValues>,
     pub local_name: Atom,
     pub classes: Vec<Atom>,
     pub namespace: Namespace,
     pub common_style_affecting_attributes: CommonStyleAffectingAttributes,
     pub link: bool,
 }
 
-impl<C: ComputedValues> PartialEq for StyleSharingCandidate<C> {
+impl PartialEq for StyleSharingCandidate {
     fn eq(&self, other: &Self) -> bool {
         arc_ptr_eq(&self.style, &other.style) &&
             arc_ptr_eq(&self.parent_style, &other.parent_style) &&
             self.local_name == other.local_name &&
             self.classes == other.classes &&
             self.link == other.link &&
             self.namespace == other.namespace &&
             self.common_style_affecting_attributes == other.common_style_affecting_attributes
     }
 }
 
-impl<C: ComputedValues> StyleSharingCandidate<C> {
+impl StyleSharingCandidate {
     /// Attempts to create a style sharing candidate from this node. Returns
     /// the style sharing candidate or `None` if this node is ineligible for
     /// style sharing.
     #[allow(unsafe_code)]
-    fn new<N: TNode<ConcreteComputedValues=C>>(element: &N::ConcreteElement) -> Option<Self> {
+    fn new<N: TNode>(element: &N::ConcreteElement) -> Option<Self> {
         let parent_element = match element.parent_element() {
             None => return None,
             Some(parent_element) => parent_element,
         };
 
         let style = unsafe {
             match element.as_node().borrow_data_unchecked() {
                 None => return None,
@@ -324,28 +324,28 @@ impl<C: ComputedValues> StyleSharingCand
         // be some logic here.
 
         true
     }
 }
 
 static STYLE_SHARING_CANDIDATE_CACHE_SIZE: usize = 40;
 
-impl<C: ComputedValues> StyleSharingCandidateCache<C> {
+impl StyleSharingCandidateCache {
     pub fn new() -> Self {
         StyleSharingCandidateCache {
             cache: LRUCache::new(STYLE_SHARING_CANDIDATE_CACHE_SIZE),
         }
     }
 
-    pub fn iter(&self) -> Iter<(StyleSharingCandidate<C>, ())> {
+    pub fn iter(&self) -> Iter<(StyleSharingCandidate, ())> {
         self.cache.iter()
     }
 
-    pub fn insert_if_possible<N: TNode<ConcreteComputedValues=C>>(&mut self, element: &N::ConcreteElement) {
+    pub fn insert_if_possible<N: TNode>(&mut self, element: &N::ConcreteElement) {
         match StyleSharingCandidate::new::<N>(element) {
             None => {}
             Some(candidate) => self.cache.insert(candidate, ())
         }
     }
 
     pub fn touch(&mut self, index: usize) {
         self.cache.touch(index);
@@ -357,32 +357,32 @@ pub enum StyleSharingResult<ConcreteRest
     /// We didn't find anybody to share the style with.
     CannotShare,
     /// The node's style can be shared. The integer specifies the index in the LRU cache that was
     /// hit and the damage that was done.
     StyleWasShared(usize, ConcreteRestyleDamage),
 }
 
 trait PrivateMatchMethods: TNode
-    where <Self::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues = Self::ConcreteComputedValues> {
+    where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
     /// Actually cascades style for a node or a pseudo-element of a node.
     ///
     /// Note that animations only apply to nodes or ::before or ::after
     /// pseudo-elements.
     fn cascade_node_pseudo_element<'a, Ctx>(&self,
                                             context: &Ctx,
-                                            parent_style: Option<&Arc<Self::ConcreteComputedValues>>,
+                                            parent_style: Option<&Arc<ComputedValues>>,
                                             applicable_declarations: &[DeclarationBlock],
-                                            mut style: Option<&mut Arc<Self::ConcreteComputedValues>>,
+                                            mut style: Option<&mut Arc<ComputedValues>>,
                                             applicable_declarations_cache:
-                                             &mut ApplicableDeclarationsCache<Self::ConcreteComputedValues>,
+                                             &mut ApplicableDeclarationsCache,
                                             shareable: bool,
                                             animate_properties: bool)
-                                            -> (Self::ConcreteRestyleDamage, Arc<Self::ConcreteComputedValues>)
-    where Ctx: StyleContext<'a, <Self::ConcreteElement as Element>::Impl> {
+                                            -> (Self::ConcreteRestyleDamage, Arc<ComputedValues>)
+    where Ctx: StyleContext<'a> {
         let mut cacheable = true;
         let shared_context = context.shared_context();
         if animate_properties {
             cacheable = !self.update_animations_for_cascade(shared_context,
                                                             &mut style) && cacheable;
         }
 
         let this_style;
@@ -416,27 +416,27 @@ trait PrivateMatchMethods: TNode
         };
 
         let mut this_style = Arc::new(this_style);
 
         if animate_properties {
             let new_animations_sender = &context.local_context().new_animations_sender;
             let this_opaque = self.opaque();
             // Trigger any present animations if necessary.
-            let mut animations_started = animation::maybe_start_animations::<<Self::ConcreteElement as Element>::Impl>(
+            let mut animations_started = animation::maybe_start_animations(
                 &shared_context,
                 new_animations_sender,
                 this_opaque,
                 &this_style);
 
             // Trigger transitions if necessary. This will reset `this_style` back
             // to its old value if it did trigger a transition.
             if let Some(ref style) = style {
                 animations_started |=
-                    animation::start_transitions_if_applicable::<<Self::ConcreteElement as Element>::Impl>(
+                    animation::start_transitions_if_applicable(
                         new_animations_sender,
                         this_opaque,
                         &**style,
                         &mut this_style);
             }
 
             cacheable = cacheable && !animations_started
         }
@@ -450,18 +450,18 @@ trait PrivateMatchMethods: TNode
                                                  this_style.clone());
         }
 
         // Return the final style and the damage done to our caller.
         (damage, this_style)
     }
 
     fn update_animations_for_cascade(&self,
-                                     context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
-                                     style: &mut Option<&mut Arc<Self::ConcreteComputedValues>>)
+                                     context: &SharedStyleContext,
+                                     style: &mut Option<&mut Arc<ComputedValues>>)
                                      -> bool {
         let style = match *style {
             None => return false,
             Some(ref mut style) => style,
         };
 
         // Finish any expired transitions.
         let this_opaque = self.opaque();
@@ -501,43 +501,41 @@ trait PrivateMatchMethods: TNode
                 //
                 // Thus, we can't assume all the animations have been already
                 // updated by layout, because other restyle due to script might
                 // be triggered by layout before the animation tick.
                 //
                 // See #12171 and the associated PR for an example where this
                 // happened while debugging other release panic.
                 if !running_animation.is_expired() {
-                    animation::update_style_for_animation::<Self::ConcreteRestyleDamage,
-                        <Self::ConcreteElement as Element>::Impl>(context, running_animation, style, None);
+                    animation::update_style_for_animation::<Self::ConcreteRestyleDamage>(
+                        context, running_animation, style, None);
                     running_animation.mark_as_expired();
                 }
             }
         }
 
         had_animations_to_expire || had_running_animations
     }
 }
 
 impl<N: TNode> PrivateMatchMethods for N
-    where <N::ConcreteElement as Element>::Impl:
-                SelectorImplExt<ComputedValues = N::ConcreteComputedValues> {}
+    where <N::ConcreteElement as Element>::Impl: SelectorImplExt {}
 
 trait PrivateElementMatchMethods: TElement {
     fn share_style_with_candidate_if_possible(&self,
                                               parent_node: Option<Self::ConcreteNode>,
-                                              candidate: &StyleSharingCandidate<<Self::ConcreteNode as
-                                                                                 TNode>::ConcreteComputedValues>)
-                                              -> Option<Arc<<Self::ConcreteNode as TNode>::ConcreteComputedValues>> {
+                                              candidate: &StyleSharingCandidate)
+                                              -> Option<Arc<ComputedValues>> {
         let parent_node = match parent_node {
             Some(ref parent_node) if parent_node.as_element().is_some() => parent_node,
             Some(_) | None => return None,
         };
 
-        let parent_data: Option<&PrivateStyleData<_, _>> = unsafe {
+        let parent_data: Option<&PrivateStyleData> = unsafe {
             parent_node.borrow_data_unchecked().map(|d| &*d)
         };
 
         if let Some(parent_data_ref) = parent_data {
             // Check parent style.
             let parent_style = (*parent_data_ref).style.as_ref().unwrap();
             if !arc_ptr_eq(parent_style, &candidate.parent_style) {
                 return None
@@ -549,50 +547,48 @@ trait PrivateElementMatchMethods: TEleme
             return Some(candidate.style.clone())
         }
         None
     }
 }
 
 impl<E: TElement> PrivateElementMatchMethods for E {}
 
-pub trait ElementMatchMethods : TElement
-    where Self::Impl: SelectorImplExt {
+pub trait ElementMatchMethods : TElement {
     fn match_element(&self,
-                     stylist: &Stylist<Self::Impl>,
+                     stylist: &Stylist,
                      parent_bf: Option<&BloomFilter>,
-                     applicable_declarations: &mut ApplicableDeclarations<Self::Impl>)
+                     applicable_declarations: &mut ApplicableDeclarations)
                      -> bool {
         let style_attribute = self.style_attribute().as_ref();
 
         applicable_declarations.normal_shareable =
             stylist.push_applicable_declarations(self,
                                                  parent_bf,
                                                  style_attribute,
                                                  None,
                                                  &mut applicable_declarations.normal);
-        Self::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
+        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.normal_shareable &&
         applicable_declarations.per_pseudo.values().all(|v| v.is_empty())
     }
 
     /// Attempts to share a style with another node. This method is unsafe because it depends on
     /// the `style_sharing_candidate_cache` having only live nodes in it, and we have no way to
     /// guarantee that at the type system level yet.
     unsafe fn share_style_if_possible(&self,
                                       style_sharing_candidate_cache:
-                                        &mut StyleSharingCandidateCache<<Self::ConcreteNode as
-                                                                         TNode>::ConcreteComputedValues>,
+                                        &mut StyleSharingCandidateCache,
                                       parent: Option<Self::ConcreteNode>)
                                       -> StyleSharingResult<<Self::ConcreteNode as TNode>::ConcreteRestyleDamage> {
         if opts::get().disable_share_style_cache {
             return StyleSharingResult::CannotShare
         }
 
         if self.style_attribute().is_some() {
             return StyleSharingResult::CannotShare
@@ -667,21 +663,18 @@ pub trait MatchMethods : TNode {
             // TODO: case-sensitivity depends on the document type and quirks mode
             element.each_class(|class| bf.remove(class));
         }
     }
 
     unsafe fn cascade_node<'a, Ctx>(&self,
                                     context: &Ctx,
                                     parent: Option<Self>,
-                                    applicable_declarations:
-                                     &ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>)
-    where <Self::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues = Self::ConcreteComputedValues>,
-          Ctx: StyleContext<'a, <Self::ConcreteElement as Element>::Impl>
-    {
+                                    applicable_declarations: &ApplicableDeclarations)
+    where Ctx: StyleContext<'a> {
         // Get our parent's style. This must be unsafe so that we don't touch the parent's
         // borrow flags.
         //
         // FIXME(pcwalton): Isolate this unsafety into the `wrapper` module to allow
         // enforced safe, race-free access to the parent style.
         let parent_style = match parent {
             Some(parent_node) => {
                 let parent_style = (*parent_node.borrow_data_unchecked().unwrap()).style.as_ref().unwrap();
@@ -692,17 +685,17 @@ pub trait MatchMethods : TNode {
 
         let mut applicable_declarations_cache =
             context.local_context().applicable_declarations_cache.borrow_mut();
 
         let damage;
         if self.is_text_node() {
             let mut data_ref = self.mutate_data().unwrap();
             let mut data = &mut *data_ref;
-            let cloned_parent_style = Self::ConcreteComputedValues::style_for_child_text_node(parent_style.unwrap());
+            let cloned_parent_style = ComputedValues::style_for_child_text_node(parent_style.unwrap());
             damage = Self::ConcreteRestyleDamage::compute(data.style.as_ref(),
                                                           &*cloned_parent_style);
             data.style = Some(cloned_parent_style);
         } else {
             damage = {
                 let mut data_ref = self.mutate_data().unwrap();
                 let mut data = &mut *data_ref;
                 let (mut damage, final_style) = self.cascade_node_pseudo_element(
--- a/servo/components/style/properties/build.py
+++ b/servo/components/style/properties/build.py
@@ -13,32 +13,32 @@ sys.path.insert(0, BASE)  # For importin
 from mako import exceptions
 from mako.lookup import TemplateLookup
 from mako.template import Template
 
 import data
 
 
 def main():
-    usage = "Usage: %s [ servo | gecko ] [ style-crate | geckolib | html ]" % sys.argv[0]
+    usage = "Usage: %s [ servo | gecko ] [ style-crate | html ]" % sys.argv[0]
     if len(sys.argv) < 3:
         abort(usage)
     product = sys.argv[1]
     output = sys.argv[2]
     if product not in ["servo", "gecko"] or output not in ["style-crate", "geckolib", "html"]:
         abort(usage)
 
     properties = data.PropertiesData(product=product)
     rust = render(os.path.join(BASE, "properties.mako.rs"), product=product, data=properties)
     if output == "style-crate":
         write(os.environ["OUT_DIR"], "properties.rs", rust)
-    if output == "geckolib":
-        template = os.path.join(BASE, "..", "..", "..", "ports", "geckolib", "properties.mako.rs")
-        rust = render(template, data=properties)
-        write(os.environ["OUT_DIR"], "properties.rs", rust)
+        if product == "gecko":
+            template = os.path.join(BASE, "gecko.mako.rs")
+            rust = render(template, data=properties)
+            write(os.environ["OUT_DIR"], "gecko_properties.rs", rust)
     elif output == "html":
         write_html(properties)
 
 
 def abort(message):
     sys.stderr.write(message + b"\n")
     sys.exit(1)
 
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -112,21 +112,20 @@ class Method(object):
         return self.signature() + ";"
 
     def stub(self):
         return self.signature() + "{ unimplemented!() }"
 
 
 class StyleStruct(object):
     def __init__(self, name, inherited, gecko_name=None, additional_methods=None):
-        self.servo_struct_name = "Servo" + name
         self.gecko_struct_name = "Gecko" + name
-        self.trait_name = name
-        self.trait_name_lower = name.lower()
-        self.ident = to_rust_ident(self.trait_name_lower)
+        self.name = name
+        self.name_lower = name.lower()
+        self.ident = to_rust_ident(self.name_lower)
         self.longhands = []
         self.inherited = inherited
         self.gecko_name = gecko_name or name
         self.gecko_ffi_name = "nsStyle" + self.gecko_name
         self.additional_methods = additional_methods or []
 
 
 class PropertiesData(object):
rename from servo/ports/geckolib/properties.mako.rs
rename to servo/components/style/properties/gecko.mako.rs
--- a/servo/ports/geckolib/properties.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -5,163 +5,170 @@
 // `data` comes from components/style/properties.mako.rs; see build.rs for more details.
 
 <%!
     from data import to_rust_ident
     from data import Keyword
 %>
 
 use app_units::Au;
+use custom_properties::ComputedValuesMap;
 % for style_struct in data.style_structs:
 use gecko_bindings::structs::${style_struct.gecko_ffi_name};
 use gecko_bindings::bindings::Gecko_Construct_${style_struct.gecko_ffi_name};
 use gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ffi_name};
 use gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name};
 % endfor
 use gecko_bindings::bindings::{Gecko_CopyMozBindingFrom, Gecko_CopyListStyleTypeFrom};
 use gecko_bindings::bindings::{Gecko_SetMozBinding, Gecko_SetListStyleType};
 use gecko_bindings::bindings::{Gecko_SetNullImageValue, Gecko_SetGradientImageValue};
 use gecko_bindings::bindings::{Gecko_EnsureImageLayersLength, Gecko_CreateGradient};
 use gecko_bindings::bindings::{Gecko_CopyImageValueFrom, Gecko_CopyFontFamilyFrom};
 use gecko_bindings::bindings::{Gecko_FontFamilyList_AppendGeneric, Gecko_FontFamilyList_AppendNamed};
 use gecko_bindings::bindings::{Gecko_FontFamilyList_Clear, Gecko_InitializeImageLayer};
+use gecko_bindings::bindings;
 use gecko_bindings::structs;
-use glue::ArcHelpers;
+use gecko_glue::ArcHelpers;
+use gecko_values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
+use gecko_values::convert_rgba_to_nscolor;
+use gecko_values::round_border_to_device_pixels;
+use logical_geometry::WritingMode;
+use properties::CascadePropertyFn;
+use properties::longhands;
 use std::fmt::{self, Debug};
 use std::mem::{transmute, uninitialized, zeroed};
 use std::sync::Arc;
 use std::cmp;
-use style::custom_properties::ComputedValuesMap;
-use style::logical_geometry::WritingMode;
-use style::properties::{CascadePropertyFn, ServoComputedValues, ComputedValues};
-use style::properties::longhands;
-use style::properties::style_struct_traits::*;
-use values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
-use values::convert_rgba_to_nscolor;
-use values::round_border_to_device_pixels;
+
+pub mod style_structs {
+    % for style_struct in data.style_structs:
+    pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
+    % endfor
+}
 
 #[derive(Clone, Debug)]
-pub struct GeckoComputedValues {
+pub struct ComputedValues {
     % for style_struct in data.style_structs:
-    ${style_struct.ident}: Arc<${style_struct.gecko_struct_name}>,
+    ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
 
     custom_properties: Option<Arc<ComputedValuesMap>>,
     shareable: bool,
     pub writing_mode: WritingMode,
     pub root_font_size: Au,
 }
 
-impl GeckoComputedValues {
+impl ComputedValues {
     pub fn inherit_from(parent: &Arc<Self>) -> Arc<Self> {
-        Arc::new(GeckoComputedValues {
+        Arc::new(ComputedValues {
             custom_properties: parent.custom_properties.clone(),
             shareable: parent.shareable,
             writing_mode: parent.writing_mode,
             root_font_size: parent.root_font_size,
             % for style_struct in data.style_structs:
             % if style_struct.inherited:
             ${style_struct.ident}: parent.${style_struct.ident}.clone(),
             % else:
             ${style_struct.ident}: Self::initial_values().${style_struct.ident}.clone(),
             % endif
             % endfor
         })
     }
-}
 
-impl ComputedValues for GeckoComputedValues {
-% for style_struct in data.style_structs:
-    type Concrete${style_struct.trait_name} = ${style_struct.gecko_struct_name};
-% endfor
-
-    fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
+    pub fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
            shareable: bool,
            writing_mode: WritingMode,
            root_font_size: Au,
             % for style_struct in data.style_structs:
-           ${style_struct.ident}: Arc<${style_struct.gecko_struct_name}>,
+           ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
             % endfor
     ) -> Self {
-        GeckoComputedValues {
+        ComputedValues {
             custom_properties: custom_properties,
             shareable: shareable,
             writing_mode: writing_mode,
             root_font_size: root_font_size,
             % for style_struct in data.style_structs:
             ${style_struct.ident}: ${style_struct.ident},
             % endfor
         }
     }
 
-    fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
+    pub fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
         // Gecko expects text nodes to be styled as if they were elements that
         // matched no rules (that is, inherited style structs are inherited and
         // non-inherited style structs are set to their initial values).
-        GeckoComputedValues::inherit_from(parent)
+        ComputedValues::inherit_from(parent)
     }
 
-    fn initial_values() -> &'static Self { &*INITIAL_GECKO_VALUES }
+    pub fn initial_values() -> &'static Self { &*INITIAL_GECKO_VALUES }
 
     #[inline]
-    fn do_cascade_property<F: FnOnce(&[CascadePropertyFn<Self>])>(f: F) {
+    pub fn do_cascade_property<F: FnOnce(&[CascadePropertyFn])>(f: F) {
         f(&CASCADE_PROPERTY)
     }
 
     % for style_struct in data.style_structs:
     #[inline]
-    fn clone_${style_struct.trait_name_lower}(&self) -> Arc<Self::Concrete${style_struct.trait_name}> {
+    pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
         self.${style_struct.ident}.clone()
     }
     #[inline]
-    fn get_${style_struct.trait_name_lower}<'a>(&'a self) -> &'a Self::Concrete${style_struct.trait_name} {
+    pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
         &self.${style_struct.ident}
     }
     #[inline]
-    fn mutate_${style_struct.trait_name_lower}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.trait_name} {
+    pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
         Arc::make_mut(&mut self.${style_struct.ident})
     }
     % endfor
 
-    fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> { self.custom_properties.as_ref().map(|x| x.clone())}
-    fn root_font_size(&self) -> Au { self.root_font_size }
-    fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; }
-    fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }
+    pub fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> {
+        self.custom_properties.as_ref().map(|x| x.clone())
+    }
+
+    pub fn root_font_size(&self) -> Au { self.root_font_size }
+    pub fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; }
+    pub fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }
 
     // FIXME(bholley): Implement this properly.
     #[inline]
-    fn is_multicol(&self) -> bool { false }
+    pub fn is_multicol(&self) -> bool { false }
 }
 
 <%def name="declare_style_struct(style_struct)">
 pub struct ${style_struct.gecko_struct_name} {
     gecko: ${style_struct.gecko_ffi_name},
 }
 </%def>
 
 <%def name="impl_simple_setter(ident, gecko_ffi_name)">
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         ${set_gecko_property(gecko_ffi_name, "v")}
     }
 </%def>
 
 <%def name="impl_simple_clone(ident, gecko_ffi_name)">
-    fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         self.gecko.${gecko_ffi_name}
     }
 </%def>
 
 <%def name="impl_simple_copy(ident, gecko_ffi_name, *kwargs)">
-    fn copy_${ident}_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
         self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
     }
 </%def>
 
 <%def name="impl_coord_copy(ident, gecko_ffi_name)">
-    fn copy_${ident}_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
         self.gecko.${gecko_ffi_name}.copy_from(&other.gecko.${gecko_ffi_name});
     }
 </%def>
 
 <%!
 def is_border_style_masked(ffi_name):
     return ffi_name.split("[")[0] in ["mBorderStyle", "mOutlineStyle", "mTextDecorationStyle"]
 
@@ -175,31 +182,33 @@ def set_gecko_property(ffi_name, expr):
         return "self.gecko.%s &= !(structs::BORDER_STYLE_MASK as u8);" % ffi_name + \
                "self.gecko.%s |= %s as u8;" % (ffi_name, expr)
     elif ffi_name == "__LIST_STYLE_TYPE__":
         return "unsafe { Gecko_SetListStyleType(&mut self.gecko, %s as u32); }" % expr
     return "self.gecko.%s = %s;" % (ffi_name, expr)
 %>
 
 <%def name="impl_keyword_setter(ident, gecko_ffi_name, keyword)">
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
-        use style::properties::longhands::${ident}::computed_value::T as Keyword;
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+        use properties::longhands::${ident}::computed_value::T as Keyword;
         // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
         let result = match v {
             % for value in keyword.values_for('gecko'):
                 Keyword::${to_rust_ident(value)} => structs::${keyword.gecko_constant(value)} as u8,
             % endfor
         };
         ${set_gecko_property(gecko_ffi_name, "result")}
     }
 </%def>
 
 <%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword)">
-    fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-        use style::properties::longhands::${ident}::computed_value::T as Keyword;
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+        use properties::longhands::${ident}::computed_value::T as Keyword;
         // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
         match ${get_gecko_property(gecko_ffi_name)} as u32 {
             % for value in keyword.values_for('gecko'):
             structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)},
             % endfor
             x => panic!("Found unexpected value in style struct for ${ident} property: {}", x),
         }
     }
@@ -227,44 +236,47 @@ def set_gecko_property(ffi_name, expr):
 </%def>
 
 <%def name="get_current_color_flag_from(field)">
     (${field} & (structs::BORDER_COLOR_FOREGROUND as u8)) != 0
 </%def>
 
 <%def name="impl_color_setter(ident, gecko_ffi_name, color_flags_ffi_name=None)">
     #[allow(unreachable_code)]
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         use cssparser::Color;
         ${clear_color_flags(color_flags_ffi_name)}
         let result = match v {
             Color::CurrentColor => {
                 ${set_current_color_flag(color_flags_ffi_name)}
                 0
             },
             Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba),
         };
         ${set_gecko_property(gecko_ffi_name, "result")}
     }
 </%def>
 
 <%def name="impl_color_copy(ident, gecko_ffi_name, color_flags_ffi_name=None)">
-    fn copy_${ident}_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
         % if color_flags_ffi_name:
             ${clear_color_flags(color_flags_ffi_name)}
             if ${get_current_color_flag_from("other.gecko." + color_flags_ffi_name)} {
                 ${set_current_color_flag(color_flags_ffi_name)}
             }
         % endif
         self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}
     }
 </%def>
 
 <%def name="impl_color_clone(ident, gecko_ffi_name, color_flags_ffi_name=None)">
-    fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         use cssparser::Color;
         % if color_flags_ffi_name:
             if ${get_current_color_flag_from("self.gecko." + color_flags_ffi_name)} {
                 return Color::CurrentColor
             }
         % endif
         Color::RGBA(convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)}))
     }
@@ -290,97 +302,105 @@ def set_gecko_property(ffi_name, expr):
 <%call expr="impl_color_setter(ident, gecko_ffi_name, color_flags_ffi_name)"></%call>
 <%call expr="impl_color_copy(ident, gecko_ffi_name, color_flags_ffi_name)"></%call>
 % if need_clone:
     <%call expr="impl_color_clone(ident, gecko_ffi_name, color_flags_ffi_name)"></%call>
 % endif
 </%def>
 
 <%def name="impl_app_units(ident, gecko_ffi_name, need_clone, round_to_pixels=False)">
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         % if round_to_pixels:
         let au_per_device_px = Au(self.gecko.mTwipsPerPixel);
         self.gecko.${gecko_ffi_name} = round_border_to_device_pixels(v, au_per_device_px).0;
         % else:
         self.gecko.${gecko_ffi_name} = v.0;
         % endif
     }
 <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
 %if need_clone:
-    fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         Au(self.gecko.${gecko_ffi_name})
     }
 % endif
 </%def>
 
 <%def name="impl_split_style_coord(ident, unit_ffi_name, union_ffi_name, need_clone=False)">
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         v.to_gecko_style_coord(&mut self.gecko.${unit_ffi_name},
                                &mut self.gecko.${union_ffi_name});
     }
-    fn copy_${ident}_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
         unsafe { self.gecko.${union_ffi_name}.reset(&mut self.gecko.${unit_ffi_name}) };
         self.gecko.${unit_ffi_name} =  other.gecko.${unit_ffi_name};
         self.gecko.${union_ffi_name} = other.gecko.${union_ffi_name};
         unsafe { self.gecko.${union_ffi_name}.addref_if_calc(&self.gecko.${unit_ffi_name}) };
     }
     % if need_clone:
-        fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-            use style::properties::longhands::${ident}::computed_value::T;
+        #[allow(non_snake_case)]
+        pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+            use properties::longhands::${ident}::computed_value::T;
             T::from_gecko_style_coord(&self.gecko.${unit_ffi_name},
                                       &self.gecko.${union_ffi_name})
                 .expect("clone for ${ident} failed")
         }
     % endif
 </%def>
 
 <%def name="impl_style_coord(ident, gecko_ffi_name, need_clone=False)">
 ${impl_split_style_coord(ident,
                          "%s.mUnit" % gecko_ffi_name,
                          "%s.mValue" % gecko_ffi_name,
                          need_clone=need_clone)}
 </%def>
 
 <%def name="impl_corner_style_coord(ident, x_unit_ffi_name, x_union_ffi_name, \
                                     y_unit_ffi_name, y_union_ffi_name, need_clone=False)">
-    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         v.0.width.to_gecko_style_coord(&mut self.gecko.${x_unit_ffi_name},
                                        &mut self.gecko.${x_union_ffi_name});
         v.0.height.to_gecko_style_coord(&mut self.gecko.${y_unit_ffi_name},
                                         &mut self.gecko.${y_union_ffi_name});
     }
-    fn copy_${ident}_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
         unsafe { self.gecko.${x_union_ffi_name}.reset(&mut self.gecko.${x_unit_ffi_name}) };
         unsafe { self.gecko.${y_union_ffi_name}.reset(&mut self.gecko.${y_unit_ffi_name}) };
         self.gecko.${x_unit_ffi_name} = other.gecko.${x_unit_ffi_name};
         self.gecko.${x_union_ffi_name} = other.gecko.${x_union_ffi_name};
         self.gecko.${y_unit_ffi_name} = other.gecko.${y_unit_ffi_name};
         self.gecko.${y_union_ffi_name} = other.gecko.${y_union_ffi_name};
         unsafe { self.gecko.${x_union_ffi_name}.addref_if_calc(&self.gecko.${x_unit_ffi_name}) };
         unsafe { self.gecko.${y_union_ffi_name}.addref_if_calc(&self.gecko.${y_unit_ffi_name}) };
     }
     % if need_clone:
-        fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-            use style::properties::longhands::${ident}::computed_value::T;
+        #[allow(non_snake_case)]
+        pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+            use properties::longhands::${ident}::computed_value::T;
             use euclid::Size2D;
             let width = GeckoStyleCoordConvertible::from_gecko_style_coord(&self.gecko.${x_unit_ffi_name},
                                                                            &self.gecko.${x_union_ffi_name})
                             .expect("Failed to clone ${ident}");
             let height = GeckoStyleCoordConvertible::from_gecko_style_coord(&self.gecko.${y_unit_ffi_name},
                                                                             &self.gecko.${y_union_ffi_name})
                             .expect("Failed to clone ${ident}");
             T(Size2D::new(width, height))
         }
     % endif
 </%def>
 
 <%def name="impl_style_struct(style_struct)">
 impl ${style_struct.gecko_struct_name} {
     #[allow(dead_code, unused_variables)]
-    fn initial() -> Arc<Self> {
+    pub fn initial() -> Arc<Self> {
         let mut result = Arc::new(${style_struct.gecko_struct_name} { gecko: unsafe { zeroed() } });
         unsafe {
             Gecko_Construct_${style_struct.gecko_ffi_name}(&mut Arc::make_mut(&mut result).gecko);
         }
         result
     }
     pub fn get_gecko(&self) -> &${style_struct.gecko_ffi_name} {
         &self.gecko
@@ -450,17 +470,17 @@ impl Debug for ${style_struct.gecko_stru
        "Opacity": impl_simple,
    }
 
    keyword_longhands = [x for x in longhands if x.keyword and not x.name in force_stub]
    predefined_longhands = [x for x in longhands
                            if x.predefined_type in predefined_types and not x.name in force_stub]
    stub_longhands = [x for x in longhands if x not in keyword_longhands + predefined_longhands]
 %>
-impl ${style_struct.trait_name} for ${style_struct.gecko_struct_name} {
+impl ${style_struct.gecko_struct_name} {
     /*
      * Manually-Implemented Methods.
      */
     ${caller.body().strip()}
 
     /*
      * Auto-Generated Methods.
      */
@@ -471,49 +491,53 @@ impl ${style_struct.trait_name} for ${st
         impl_fn = predefined_types[longhand.predefined_type]
         impl_fn(longhand.ident, longhand.gecko_ffi_name, need_clone=longhand.need_clone)
     %>
 
     /*
      * Stubs.
      */
     % for longhand in stub_longhands:
-    fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) {
+    #[allow(non_snake_case)]
+    pub fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) {
         if cfg!(debug_assertions) {
             println!("stylo: Unimplemented property setter: ${longhand.name}");
         }
     }
-    fn copy_${longhand.ident}_from(&mut self, _: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy_${longhand.ident}_from(&mut self, _: &Self) {
         if cfg!(debug_assertions) {
             println!("stylo: Unimplemented property setter: ${longhand.name}");
         }
     }
     % if longhand.need_clone:
-    fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
+    #[allow(non_snake_case)]
+    pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
         unimplemented!()
     }
     % endif
     % if longhand.need_index:
-    fn ${longhand.ident}_count(&self) -> usize { 0 }
-    fn ${longhand.ident}_at(&self, _index: usize) -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
+    pub fn ${longhand.ident}_count(&self) -> usize { 0 }
+    pub fn ${longhand.ident}_at(&self, _index: usize)
+                                -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
         unimplemented!()
     }
     % endif
     % endfor
     <% additionals = [x for x in style_struct.additional_methods
                       if skip_additionals != "*" and not x.name in skip_additionals.split()] %>
     % for additional in additionals:
     ${additional.stub()}
     % endfor
 }
 </%def>
 
 <% data.manual_style_structs = [] %>
 <%def name="impl_trait(style_struct_name, skip_longhands='', skip_additionals='')">
-<%self:raw_impl_trait style_struct="${next(x for x in data.style_structs if x.trait_name == style_struct_name)}"
+<%self:raw_impl_trait style_struct="${next(x for x in data.style_structs if x.name == style_struct_name)}"
                       skip_longhands="${skip_longhands}" skip_additionals="${skip_additionals}">
 ${caller.body()}
 </%self:raw_impl_trait>
 <% data.manual_style_structs.append(style_struct_name) %>
 </%def>
 
 <%!
 class Side(object):
@@ -566,17 +590,17 @@ fn static_assert() {
                     need_clone=True) %>
 
     <% impl_color("border_%s_color" % side.ident, "mBorderColor[%s]" % side.index,
                   color_flags_ffi_name="mBorderStyle[%s]" % side.index, need_clone=True) %>
 
     <% impl_app_units("border_%s_width" % side.ident, "mComputedBorder.%s" % side.ident, need_clone=True,
                       round_to_pixels=True) %>
 
-    fn border_${side.ident}_has_nonzero_width(&self) -> bool {
+    pub fn border_${side.ident}_has_nonzero_width(&self) -> bool {
         self.gecko.mComputedBorder.${side.ident} != 0
     }
     % endfor
 
     % for corner in CORNERS:
     <% impl_corner_style_coord("border_%s_radius" % corner.ident,
                                "mBorderRadius.mUnits[%s]" % corner.x_index,
                                "mBorderRadius.mValues[%s]" % corner.x_index,
@@ -616,46 +640,46 @@ fn static_assert() {
 
     % for side in SIDES:
     <% impl_split_style_coord("%s" % side.ident,
                               "mOffset.mUnits[%s]" % side.index,
                               "mOffset.mValues[%s]" % side.index,
                               need_clone=True) %>
     % endfor
 
-    fn set_z_index(&mut self, v: longhands::z_index::computed_value::T) {
-        use style::properties::longhands::z_index::computed_value::T;
+    pub fn set_z_index(&mut self, v: longhands::z_index::computed_value::T) {
+        use properties::longhands::z_index::computed_value::T;
         match v {
             T::Auto => self.gecko.mZIndex.set_auto(),
             T::Number(n) => self.gecko.mZIndex.set_int(n),
         }
     }
 
-    fn copy_z_index_from(&mut self, other: &Self) {
+    pub fn copy_z_index_from(&mut self, other: &Self) {
         use gecko_bindings::structs::nsStyleUnit;
         // z-index is never a calc(). If it were, we'd be leaking here, so
         // assert that it isn't.
         debug_assert!(self.gecko.mZIndex.mUnit != nsStyleUnit::eStyleUnit_Calc);
         self.gecko.mZIndex.mUnit = other.gecko.mZIndex.mUnit;
         self.gecko.mZIndex.mValue = other.gecko.mZIndex.mValue;
     }
 
-    fn clone_z_index(&self) -> longhands::z_index::computed_value::T {
-        use style::properties::longhands::z_index::computed_value::T;
+    pub fn clone_z_index(&self) -> longhands::z_index::computed_value::T {
+        use properties::longhands::z_index::computed_value::T;
 
         if self.gecko.mZIndex.is_auto() {
             return T::Auto;
         }
 
         debug_assert!(self.gecko.mZIndex.is_int());
         T::Number(self.gecko.mZIndex.get_int())
     }
 
-    fn set_box_sizing(&mut self, v: longhands::box_sizing::computed_value::T) {
-        use style::computed_values::box_sizing::T;
+    pub fn set_box_sizing(&mut self, v: longhands::box_sizing::computed_value::T) {
+        use computed_values::box_sizing::T;
         use gecko_bindings::structs::StyleBoxSizing;
         // TODO: guess what to do with box-sizing: padding-box
         self.gecko.mBoxSizing = match v {
             T::content_box => StyleBoxSizing::Content,
             T::border_box => StyleBoxSizing::Border
         }
     }
     ${impl_simple_copy('box_sizing', 'mBoxSizing')}
@@ -679,27 +703,27 @@ fn static_assert() {
     % for corner in CORNERS:
     <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
                                "mOutlineRadius.mUnits[%s]" % corner.x_index,
                                "mOutlineRadius.mValues[%s]" % corner.x_index,
                                "mOutlineRadius.mUnits[%s]" % corner.y_index,
                                "mOutlineRadius.mValues[%s]" % corner.y_index) %>
     % endfor
 
-    fn outline_has_nonzero_width(&self) -> bool {
+    pub fn outline_has_nonzero_width(&self) -> bool {
         self.gecko.mActualOutlineWidth != 0
     }
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Font"
     skip_longhands="font-family font-style font-size font-weight"
     skip_additionals="*">
 
-    fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
-        use style::properties::longhands::font_family::computed_value::FontFamily;
+    pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
+        use properties::longhands::font_family::computed_value::FontFamily;
         use gecko_bindings::structs::FontFamilyType;
 
         let list = &mut self.gecko.mFont.fontlist;
         unsafe { Gecko_FontFamilyList_Clear(list); }
 
         for family in &v.0 {
             match *family {
                 FontFamily::FamilyName(ref name) => {
@@ -714,52 +738,52 @@ fn static_assert() {
                         else if name == &atom!("monospace") { FontFamilyType::eFamily_monospace }
                         else { panic!("Unknown generic font family") };
                     unsafe { Gecko_FontFamilyList_AppendGeneric(list, family_type); }
                 }
             }
         }
     }
 
-    fn copy_font_family_from(&mut self, other: &Self) {
+    pub fn copy_font_family_from(&mut self, other: &Self) {
         unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); }
     }
 
     <%call expr="impl_keyword('font_style', 'mFont.style',
         data.longhands_by_name['font-style'].keyword, need_clone=False)"></%call>
 
     // FIXME(bholley): Gecko has two different sizes, one of which (mSize) is the
     // actual computed size, and the other of which (mFont.size) is the 'display
     // size' which takes font zooming into account. We don't handle font zooming yet.
-    fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
+    pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
         self.gecko.mFont.size = v.0;
         self.gecko.mSize = v.0;
     }
-    fn copy_font_size_from(&mut self, other: &Self) {
+    pub fn copy_font_size_from(&mut self, other: &Self) {
         self.gecko.mFont.size = other.gecko.mFont.size;
         self.gecko.mSize = other.gecko.mSize;
     }
-    fn clone_font_size(&self) -> longhands::font_size::computed_value::T {
+    pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T {
         Au(self.gecko.mSize)
     }
 
-    fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) {
+    pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) {
         self.gecko.mFont.weight = v as u16;
     }
     ${impl_simple_copy('font_weight', 'mFont.weight')}
 
-    fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T {
+    pub fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T {
         debug_assert!(self.gecko.mFont.weight >= 100);
         debug_assert!(self.gecko.mFont.weight <= 900);
         debug_assert!(self.gecko.mFont.weight % 10 == 0);
         unsafe { transmute(self.gecko.mFont.weight) }
     }
 
     // This is used for PartialEq, which we don't implement for gecko style structs.
-    fn compute_font_hash(&mut self) {}
+    pub fn compute_font_hash(&mut self) {}
 
 </%self:impl_trait>
 
 <% skip_box_longhands= """display overflow-y vertical-align
                           -moz-binding page-break-before page-break-after""" %>
 <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
 
     // We manually-implement the |display| property until we get general
@@ -768,54 +792,54 @@ fn static_assert() {
                                             "table-header-group table-footer-group table-row table-column-group " +
                                             "table-column table-cell table-caption list-item flex none " +
                                             "-moz-box -moz-inline-box") %>
     ${impl_keyword('display', 'mDisplay', display_keyword, True)}
 
     // overflow-y is implemented as a newtype of overflow-x, so we need special handling.
     // We could generalize this if we run into other newtype keywords.
     <% overflow_x = data.longhands_by_name["overflow-x"] %>
-    fn set_overflow_y(&mut self, v: longhands::overflow_y::computed_value::T) {
-        use style::properties::longhands::overflow_x::computed_value::T as BaseType;
+    pub fn set_overflow_y(&mut self, v: longhands::overflow_y::computed_value::T) {
+        use properties::longhands::overflow_x::computed_value::T as BaseType;
         // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
         self.gecko.mOverflowY = match v.0 {
             % for value in overflow_x.keyword.values_for('gecko'):
                 BaseType::${to_rust_ident(value)} => structs::${overflow_x.keyword.gecko_constant(value)} as u8,
             % endfor
         };
     }
     ${impl_simple_copy('overflow_y', 'mOverflowY')}
-    fn clone_overflow_y(&self) -> longhands::overflow_y::computed_value::T {
-        use style::properties::longhands::overflow_x::computed_value::T as BaseType;
-        use style::properties::longhands::overflow_y::computed_value::T as NewType;
+    pub fn clone_overflow_y(&self) -> longhands::overflow_y::computed_value::T {
+        use properties::longhands::overflow_x::computed_value::T as BaseType;
+        use properties::longhands::overflow_y::computed_value::T as NewType;
         // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
         match self.gecko.mOverflowY as u32 {
             % for value in overflow_x.keyword.values_for('gecko'):
             structs::${overflow_x.keyword.gecko_constant(value)} => NewType(BaseType::${to_rust_ident(value)}),
             % endfor
             x => panic!("Found unexpected value in style struct for overflow_y property: {}", x),
         }
     }
 
-    fn set_vertical_align(&mut self, v: longhands::vertical_align::computed_value::T) {
+    pub fn set_vertical_align(&mut self, v: longhands::vertical_align::computed_value::T) {
         <% keyword = data.longhands_by_name["vertical-align"].keyword %>
-        use style::properties::longhands::vertical_align::computed_value::T;
+        use properties::longhands::vertical_align::computed_value::T;
         // FIXME: Align binary representations and ditch |match| for cast + static_asserts
         match v {
             % for value in keyword.values_for('gecko'):
                 T::${to_rust_ident(value)} =>
                     self.gecko.mVerticalAlign.set_enum(structs::${keyword.gecko_constant(value)} as i32),
             % endfor
             T::LengthOrPercentage(v) => self.gecko.mVerticalAlign.set(v),
         }
     }
 
-    fn clone_vertical_align(&self) -> longhands::vertical_align::computed_value::T {
-        use style::properties::longhands::vertical_align::computed_value::T;
-        use style::values::computed::LengthOrPercentage;
+    pub fn clone_vertical_align(&self) -> longhands::vertical_align::computed_value::T {
+        use properties::longhands::vertical_align::computed_value::T;
+        use values::computed::LengthOrPercentage;
 
         if self.gecko.mVerticalAlign.is_enum() {
             match self.gecko.mVerticalAlign.get_enum() as u32 {
                 % for value in keyword.values_for('gecko'):
                     structs::${keyword.gecko_constant(value)}
                         => T::${to_rust_ident(value)},
                 % endfor
                 _ => panic!("Unexpected enum variant for vertical-align"),
@@ -825,59 +849,61 @@ fn static_assert() {
                                                                &self.gecko.mVerticalAlign.mValue)
                 .expect("Expected length or percentage for vertical-align");
             T::LengthOrPercentage(v)
         }
     }
 
     <%call expr="impl_coord_copy('vertical_align', 'mVerticalAlign')"></%call>
 
-    fn set__moz_binding(&mut self, v: longhands::_moz_binding::computed_value::T) {
-        use style::properties::longhands::_moz_binding::SpecifiedValue as BindingValue;
+    #[allow(non_snake_case)]
+    pub fn set__moz_binding(&mut self, v: longhands::_moz_binding::computed_value::T) {
+        use properties::longhands::_moz_binding::SpecifiedValue as BindingValue;
         match v {
             BindingValue::None => debug_assert!(self.gecko.mBinding.mRawPtr.is_null()),
             BindingValue::Url(ref url, ref extra_data) => {
                 unsafe {
                     Gecko_SetMozBinding(&mut self.gecko,
                                         url.as_str().as_ptr(),
                                         url.as_str().len() as u32,
                                         extra_data.base.as_raw(),
                                         extra_data.referrer.as_raw(),
                                         extra_data.principal.as_raw());
                 }
             }
         }
     }
-    fn copy__moz_binding_from(&mut self, other: &Self) {
+    #[allow(non_snake_case)]
+    pub fn copy__moz_binding_from(&mut self, other: &Self) {
         unsafe { Gecko_CopyMozBindingFrom(&mut self.gecko, &other.gecko); }
     }
 
     // Temp fix for Bugzilla bug 24000.
     // Map 'auto' and 'avoid' to false, and 'always', 'left', and 'right' to true.
     // "A conforming user agent may interpret the values 'left' and 'right'
     // as 'always'." - CSS2.1, section 13.3.1
-    fn set_page_break_before(&mut self, v: longhands::page_break_before::computed_value::T) {
-        use style::computed_values::page_break_before::T;
+    pub fn set_page_break_before(&mut self, v: longhands::page_break_before::computed_value::T) {
+        use computed_values::page_break_before::T;
         let result = match v {
             T::auto   => false,
             T::always => true,
             T::avoid  => false,
             T::left   => true,
             T::right  => true
         };
         // TODO(shinglyu): Rename Gecko's struct to mPageBreakBefore
         self.gecko.mBreakBefore = result;
     }
 
     ${impl_simple_copy('page_break_before', 'mBreakBefore')}
 
     // Temp fix for Bugzilla bug 24000.
     // See set_page_break_before for detail.
-    fn set_page_break_after(&mut self, v: longhands::page_break_after::computed_value::T) {
-        use style::computed_values::page_break_after::T;
+    pub fn set_page_break_after(&mut self, v: longhands::page_break_after::computed_value::T) {
+        use computed_values::page_break_after::T;
         let result = match v {
             T::auto   => false,
             T::always => true,
             T::avoid  => false,
             T::left   => true,
             T::right  => true
         };
         // TODO(shinglyu): Rename Gecko's struct to mPageBreakBefore
@@ -895,24 +921,24 @@ fn static_assert() {
                                   background-image background-clip
                                   background-origin background-attachment""" %>
 <%self:impl_trait style_struct_name="Background"
                   skip_longhands="${skip_background_longhands}"
                   skip_additionals="*">
 
     <% impl_color("background_color", "mBackgroundColor", need_clone=True) %>
 
-    fn copy_background_repeat_from(&mut self, other: &Self) {
+    pub fn copy_background_repeat_from(&mut self, other: &Self) {
         self.gecko.mImage.mRepeatCount = cmp::min(1, other.gecko.mImage.mRepeatCount);
         self.gecko.mImage.mLayers.mFirstElement.mRepeat =
             other.gecko.mImage.mLayers.mFirstElement.mRepeat;
     }
 
-    fn set_background_repeat(&mut self, v: longhands::background_repeat::computed_value::T) {
-        use style::properties::longhands::background_repeat::computed_value::T;
+    pub fn set_background_repeat(&mut self, v: longhands::background_repeat::computed_value::T) {
+        use properties::longhands::background_repeat::computed_value::T;
         use gecko_bindings::structs::{NS_STYLE_IMAGELAYER_REPEAT_REPEAT, NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT};
         use gecko_bindings::structs::nsStyleImageLayers_Repeat;
         let (repeat_x, repeat_y) = match v {
             T::repeat_x => (NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
                             NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT),
             T::repeat_y => (NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT,
                             NS_STYLE_IMAGELAYER_REPEAT_REPEAT),
             T::repeat => (NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
@@ -923,82 +949,82 @@ fn static_assert() {
 
         self.gecko.mImage.mRepeatCount = 1;
         self.gecko.mImage.mLayers.mFirstElement.mRepeat = nsStyleImageLayers_Repeat {
             mXRepeat: repeat_x as u8,
             mYRepeat: repeat_y as u8,
         };
     }
 
-    fn copy_background_clip_from(&mut self, other: &Self) {
+    pub fn copy_background_clip_from(&mut self, other: &Self) {
         self.gecko.mImage.mClipCount = cmp::min(1, other.gecko.mImage.mClipCount);
         self.gecko.mImage.mLayers.mFirstElement.mClip =
             other.gecko.mImage.mLayers.mFirstElement.mClip;
     }
 
-    fn set_background_clip(&mut self, v: longhands::background_clip::computed_value::T) {
-        use style::properties::longhands::background_clip::computed_value::T;
+    pub fn set_background_clip(&mut self, v: longhands::background_clip::computed_value::T) {
+        use properties::longhands::background_clip::computed_value::T;
         self.gecko.mImage.mClipCount = 1;
 
         // TODO: Gecko supports background-clip: text, but just on -webkit-
         // prefixed properties.
         self.gecko.mImage.mLayers.mFirstElement.mClip = match v {
             T::border_box => structs::NS_STYLE_IMAGELAYER_CLIP_BORDER as u8,
             T::padding_box => structs::NS_STYLE_IMAGELAYER_CLIP_PADDING as u8,
             T::content_box => structs::NS_STYLE_IMAGELAYER_CLIP_CONTENT as u8,
         };
     }
 
-    fn copy_background_origin_from(&mut self, other: &Self) {
+    pub fn copy_background_origin_from(&mut self, other: &Self) {
         self.gecko.mImage.mOriginCount = cmp::min(1, other.gecko.mImage.mOriginCount);
         self.gecko.mImage.mLayers.mFirstElement.mOrigin =
             other.gecko.mImage.mLayers.mFirstElement.mOrigin;
     }
 
-    fn set_background_origin(&mut self, v: longhands::background_origin::computed_value::T) {
-        use style::properties::longhands::background_origin::computed_value::T;
+    pub fn set_background_origin(&mut self, v: longhands::background_origin::computed_value::T) {
+        use properties::longhands::background_origin::computed_value::T;
 
         self.gecko.mImage.mOriginCount = 1;
         self.gecko.mImage.mLayers.mFirstElement.mOrigin = match v {
             T::border_box => structs::NS_STYLE_IMAGELAYER_ORIGIN_BORDER as u8,
             T::padding_box => structs::NS_STYLE_IMAGELAYER_ORIGIN_PADDING as u8,
             T::content_box => structs::NS_STYLE_IMAGELAYER_ORIGIN_CONTENT as u8,
         };
     }
 
-    fn copy_background_attachment_from(&mut self, other: &Self) {
+    pub fn copy_background_attachment_from(&mut self, other: &Self) {
         self.gecko.mImage.mAttachmentCount = cmp::min(1, other.gecko.mImage.mAttachmentCount);
         self.gecko.mImage.mLayers.mFirstElement.mAttachment =
             other.gecko.mImage.mLayers.mFirstElement.mAttachment;
     }
 
-    fn set_background_attachment(&mut self, v: longhands::background_attachment::computed_value::T) {
-        use style::properties::longhands::background_attachment::computed_value::T;
+    pub fn set_background_attachment(&mut self, v: longhands::background_attachment::computed_value::T) {
+        use properties::longhands::background_attachment::computed_value::T;
 
         self.gecko.mImage.mAttachmentCount = 1;
         self.gecko.mImage.mLayers.mFirstElement.mAttachment = match v {
             T::scroll => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL as u8,
             T::fixed => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED as u8,
             T::local => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL as u8,
         };
     }
 
-    fn copy_background_image_from(&mut self, other: &Self) {
+    pub fn copy_background_image_from(&mut self, other: &Self) {
         unsafe {
             Gecko_CopyImageValueFrom(&mut self.gecko.mImage.mLayers.mFirstElement.mImage,
                                      &other.gecko.mImage.mLayers.mFirstElement.mImage);
         }
     }
 
-    fn set_background_image(&mut self, images: longhands::background_image::computed_value::T) {
+    pub fn set_background_image(&mut self, images: longhands::background_image::computed_value::T) {
         use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
         use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER};
         use gecko_bindings::structs::nsStyleCoord;
-        use style::values::computed::Image;
-        use style::values::specified::AngleOrCorner;
+        use values::computed::Image;
+        use values::specified::AngleOrCorner;
         use cssparser::Color as CSSColor;
 
         unsafe {
             // Prevent leaking of the last element we did set
             for image in &mut self.gecko.mImage.mLayers {
                 Gecko_SetNullImageValue(&mut image.mImage)
             }
             Gecko_EnsureImageLayersLength(&mut self.gecko.mImage, images.0.len());
@@ -1083,45 +1109,45 @@ fn static_assert() {
         }
     }
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="List" skip_longhands="list-style-type" skip_additionals="*">
 
     ${impl_keyword_setter("list_style_type", "__LIST_STYLE_TYPE__",
                            data.longhands_by_name["list-style-type"].keyword)}
-    fn copy_list_style_type_from(&mut self, other: &Self) {
+    pub fn copy_list_style_type_from(&mut self, other: &Self) {
         unsafe {
             Gecko_CopyListStyleTypeFrom(&mut self.gecko, &other.gecko);
         }
     }
 
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="InheritedText"
                   skip_longhands="text-align line-height">
 
     <% text_align_keyword = Keyword("text-align", "start end left right center justify -moz-center -moz-left " +
                                                   "-moz-right match-parent") %>
     ${impl_keyword('text_align', 'mTextAlign', text_align_keyword, need_clone=False)}
 
-    fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
-        use style::properties::longhands::line_height::computed_value::T;
+    pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
+        use properties::longhands::line_height::computed_value::T;
         // FIXME: Align binary representations and ditch |match| for cast + static_asserts
         match v {
             T::Normal => self.gecko.mLineHeight.set_normal(),
             T::Length(val) => self.gecko.mLineHeight.set_coord(val),
             T::Number(val) => self.gecko.mLineHeight.set_factor(val),
             T::MozBlockHeight =>
                 self.gecko.mLineHeight.set_enum(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT as i32),
         }
     }
 
-    fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
-        use style::properties::longhands::line_height::computed_value::T;
+    pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
+        use properties::longhands::line_height::computed_value::T;
         if self.gecko.mLineHeight.is_normal() {
             return T::Normal;
         }
         if self.gecko.mLineHeight.is_coord() {
             return T::Length(self.gecko.mLineHeight.get_coord());
         }
         if self.gecko.mLineHeight.is_factor() {
             return T::Number(self.gecko.mLineHeight.get_factor());
@@ -1137,44 +1163,44 @@ fn static_assert() {
 
 <%self:impl_trait style_struct_name="Text"
                   skip_longhands="text-decoration-color text-decoration-line"
                   skip_additionals="*">
 
     ${impl_color("text_decoration_color", "mTextDecorationColor",
                   color_flags_ffi_name="mTextDecorationStyle", need_clone=True)}
 
-    fn set_text_decoration_line(&mut self, v: longhands::text_decoration_line::computed_value::T) {
+    pub fn set_text_decoration_line(&mut self, v: longhands::text_decoration_line::computed_value::T) {
         let mut bits: u8 = 0;
         if v.underline {
             bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE as u8;
         }
         if v.overline {
             bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8;
         }
         if v.line_through {
             bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8;
         }
         self.gecko.mTextDecorationLine = bits;
     }
 
     ${impl_simple_copy('text_decoration_line', 'mTextDecorationLine')}
 
     #[inline]
-    fn has_underline(&self) -> bool {
+    pub fn has_underline(&self) -> bool {
         (self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE as u8)) != 0
     }
 
     #[inline]
-    fn has_overline(&self) -> bool {
+    pub fn has_overline(&self) -> bool {
         (self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8)) != 0
     }
 
     #[inline]
-    fn has_line_through(&self) -> bool {
+    pub fn has_line_through(&self) -> bool {
         (self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8)) != 0
     }
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="SVG"
                   skip_longhands="flood-color lighting-color stop-color"
                   skip_additionals="*">
 
@@ -1183,33 +1209,33 @@ fn static_assert() {
     <% impl_color("lighting_color", "mLightingColor") %>
 
     <% impl_color("stop_color", "mStopColor") %>
 
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Color"
                   skip_longhands="*">
-    fn set_color(&mut self, v: longhands::color::computed_value::T) {
+    pub fn set_color(&mut self, v: longhands::color::computed_value::T) {
         let result = convert_rgba_to_nscolor(&v);
         ${set_gecko_property("mColor", "result")}
     }
 
     <%call expr="impl_simple_copy('color', 'mColor')"></%call>
 
-    fn clone_color(&self) -> longhands::color::computed_value::T {
+    pub fn clone_color(&self) -> longhands::color::computed_value::T {
         let color = ${get_gecko_property("mColor")} as u32;
         convert_nscolor_to_rgba(color)
     }
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Pointing"
                   skip_longhands="cursor">
-    fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
-        use style::properties::longhands::cursor::computed_value::T;
+    pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
+        use properties::longhands::cursor::computed_value::T;
         use style_traits::cursor::Cursor;
 
         self.gecko.mCursor = match v {
             T::AutoCursor => structs::NS_STYLE_CURSOR_AUTO,
             T::SpecifiedCursor(cursor) => match cursor {
                 Cursor::None => structs::NS_STYLE_CURSOR_NONE,
                 Cursor::Default => structs::NS_STYLE_CURSOR_DEFAULT,
                 Cursor::Pointer => structs::NS_STYLE_CURSOR_POINTER,
@@ -1250,55 +1276,55 @@ fn static_assert() {
     }
 
     ${impl_simple_copy('cursor', 'mCursor')}
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Column"
                   skip_longhands="column-width">
 
-    fn set_column_width(&mut self, v: longhands::column_width::computed_value::T) {
+    pub fn set_column_width(&mut self, v: longhands::column_width::computed_value::T) {
         match v.0 {
             Some(au) => self.gecko.mColumnWidth.set_coord(au),
             None => self.gecko.mColumnWidth.set_auto(),
         }
     }
 
     ${impl_coord_copy('column_width', 'mColumnWidth')}
 </%self:impl_trait>
 
 <%def name="define_ffi_struct_accessor(style_struct)">
 #[no_mangle]
 #[allow(non_snake_case, unused_variables)]
-pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: *mut ServoComputedValues)
+pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: *mut bindings::ServoComputedValues)
   -> *const ${style_struct.gecko_ffi_name} {
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
-    Helpers::with(computed_values, |values| values.get_${style_struct.trait_name_lower}().get_gecko()
+    type Helpers = ArcHelpers<bindings::ServoComputedValues, ComputedValues>;
+    Helpers::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
                                                 as *const ${style_struct.gecko_ffi_name})
 }
 </%def>
 
 % for style_struct in data.style_structs:
 ${declare_style_struct(style_struct)}
 ${impl_style_struct(style_struct)}
-% if not style_struct.trait_name in data.manual_style_structs:
+% if not style_struct.name in data.manual_style_structs:
 <%self:raw_impl_trait style_struct="${style_struct}"></%self:raw_impl_trait>
 % endif
 ${define_ffi_struct_accessor(style_struct)}
 % endfor
 
 lazy_static! {
-    pub static ref INITIAL_GECKO_VALUES: GeckoComputedValues = GeckoComputedValues {
+    pub static ref INITIAL_GECKO_VALUES: ComputedValues = ComputedValues {
         % for style_struct in data.style_structs:
-           ${style_struct.ident}: ${style_struct.gecko_struct_name}::initial(),
+           ${style_struct.ident}: style_structs::${style_struct.name}::initial(),
         % endfor
         custom_properties: None,
         shareable: true,
         writing_mode: WritingMode::empty(),
         root_font_size: longhands::font_size::get_initial_value(),
     };
 }
 
-static CASCADE_PROPERTY: [CascadePropertyFn<GeckoComputedValues>; ${len(data.longhands)}] = [
+static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
     % for property in data.longhands:
         longhands::${property.ident}::cascade_property,
     % endfor
 ];
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -59,17 +59,17 @@
                     vec.iter().any(|ref x| x.has_viewport_percentage())
                 }
             }
 
             pub mod single_value {
                 use cssparser::Parser;
                 use parser::{ParserContext, ParserContextExtraData};
                 use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
-                use values::computed::{TContext, ToComputedValue};
+                use values::computed::{Context, ToComputedValue};
                 use values::{computed, specified};
                 ${caller.body()}
             }
             pub mod computed_value {
                 use super::single_value;
                 #[derive(Debug, Clone, PartialEq)]
                 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
                 pub struct T(pub Vec<single_value::computed_value::T>);
@@ -139,17 +139,17 @@
                         single_value::parse(context, parser)
                     }).map(SpecifiedValue)
                 % endif
             }
             impl ToComputedValue for SpecifiedValue {
                 type ComputedValue = computed_value::T;
 
                 #[inline]
-                fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+                fn to_computed_value(&self, context: &Context) -> computed_value::T {
                     computed_value::T(self.0.iter().map(|x| x.to_computed_value(context)).collect())
                 }
             }
         % else:
             ${caller.body()}
         % endif
     </%call>
 </%def>
@@ -165,31 +165,29 @@
         % if not property.derived_from:
             use cssparser::Parser;
             use parser::{ParserContext, ParserContextExtraData};
             use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
         % endif
         use error_reporting::ParseErrorReporter;
         use properties::longhands;
         use properties::property_bit_field::PropertyBitField;
-        use properties::{ComputedValues, ServoComputedValues, PropertyDeclaration};
-        use properties::style_struct_traits::${data.current_style_struct.trait_name};
+        use properties::{ComputedValues, PropertyDeclaration};
         use properties::style_structs;
         use std::boxed::Box as StdBox;
         use std::collections::HashMap;
         use std::sync::Arc;
-        use values::computed::{TContext, ToComputedValue};
+        use values::computed::{Context, ToComputedValue};
         use values::{computed, specified};
         use string_cache::Atom;
         ${caller.body()}
         #[allow(unused_variables)]
-        pub fn cascade_property<C: ComputedValues>(
-                                declaration: &PropertyDeclaration,
-                                inherited_style: &C,
-                                context: &mut computed::Context<C>,
+        pub fn cascade_property(declaration: &PropertyDeclaration,
+                                inherited_style: &ComputedValues,
+                                context: &mut computed::Context,
                                 seen: &mut PropertyBitField,
                                 cacheable: &mut bool,
                                 error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
             let declared_value = match *declaration {
                 PropertyDeclaration::${property.camel_case}(ref declared_value) => {
                     declared_value
                 }
                 _ => panic!("entered the wrong cascade_property() implementation"),
@@ -200,37 +198,37 @@
                 }
                 seen.set_${property.ident}();
                 {
                     let custom_props = context.style().custom_properties();
                     ::properties::substitute_variables_${property.ident}(
                         declared_value, &custom_props, |value| match *value {
                             DeclaredValue::Value(ref specified_value) => {
                                 let computed = specified_value.to_computed_value(context);
-                                context.mutate_style().mutate_${data.current_style_struct.trait_name_lower}()
+                                context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                                       .set_${property.ident}(computed);
                             }
                             DeclaredValue::WithVariables { .. } => unreachable!(),
                             DeclaredValue::Initial => {
                                 // We assume that it's faster to use copy_*_from rather than
                                 // set_*(get_initial_value());
-                                let initial_struct = C::initial_values()
-                                                      .get_${data.current_style_struct.trait_name_lower}();
-                                context.mutate_style().mutate_${data.current_style_struct.trait_name_lower}()
+                                let initial_struct = ComputedValues::initial_values()
+                                                      .get_${data.current_style_struct.name_lower}();
+                                context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                                       .copy_${property.ident}_from(initial_struct);
                             },
                             DeclaredValue::Inherit => {
                                 // This is a bit slow, but this is rare so it shouldn't
                                 // matter.
                                 //
                                 // FIXME: is it still?
                                 *cacheable = false;
                                 let inherited_struct =
-                                    inherited_style.get_${data.current_style_struct.trait_name_lower}();
-                                context.mutate_style().mutate_${data.current_style_struct.trait_name_lower}()
+                                    inherited_style.get_${data.current_style_struct.name_lower}();
+                                context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                        .copy_${property.ident}_from(inherited_struct);
                             }
                         }, error_reporter
                     );
                 }
 
                 % if property.custom_cascade:
                     cascade_property_custom(declaration,
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -19,17 +19,16 @@ use properties::longhands::box_shadow::c
 use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
 use properties::longhands::transform::computed_value::ComputedMatrix;
 use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
 use properties::longhands::transform::computed_value::T as TransformList;
 use properties::longhands::transform_origin::computed_value::T as TransformOrigin;
 use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
 use properties::longhands::visibility::computed_value::T as Visibility;
 use properties::longhands::z_index::computed_value::T as ZIndex;
-use properties::style_struct_traits::*;
 use std::cmp;
 use std::fmt;
 use super::ComputedValues;
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderRadiusSize, LengthOrNone};
 use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
 
 // NB: This needs to be here because it needs all the longhands generated
@@ -110,33 +109,34 @@ impl AnimatedProperty {
             % for prop in data.longhands:
                 % if prop.animatable:
                     AnimatedProperty::${prop.camel_case}(ref from, ref to) => from != to,
                 % endif
             % endfor
         }
     }
 
-    pub fn update<C: ComputedValues>(&self, style: &mut C, progress: f64) {
+    pub fn update(&self, style: &mut ComputedValues, progress: f64) {
         match *self {
             % for prop in data.longhands:
                 % if prop.animatable:
                     AnimatedProperty::${prop.camel_case}(ref from, ref to) => {
                         if let Ok(value) = from.interpolate(to, progress) {
                             style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
                         }
                     }
                 % endif
             % endfor
         }
     }
 
-    pub fn from_transition_property<C: ComputedValues>(transition_property: &TransitionProperty,
-                                                       old_style: &C,
-                                                       new_style: &C) -> AnimatedProperty {
+    pub fn from_transition_property(transition_property: &TransitionProperty,
+                                    old_style: &ComputedValues,
+                                    new_style: &ComputedValues)
+                                    -> AnimatedProperty {
         match *transition_property {
             TransitionProperty::All => panic!("Can't use TransitionProperty::All here."),
             % for prop in data.longhands:
                 % if prop.animatable:
                     TransitionProperty::${prop.camel_case} => {
                         AnimatedProperty::${prop.camel_case}(
                             old_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}(),
                             new_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}())
--- a/servo/components/style/properties/longhand/background.mako.rs
+++ b/servo/components/style/properties/longhand/background.mako.rs
@@ -60,17 +60,17 @@
         } else {
             Ok(SpecifiedValue(Some(try!(Image::parse(context, input)))))
         }
     }
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue(None) => computed_value::T(None),
                 SpecifiedValue(Some(ref image)) =>
                     computed_value::T(Some(image.to_computed_value(context))),
             }
         }
     }
 </%helpers:vector_longhand>
@@ -167,17 +167,17 @@
                     PositionCategory::LengthOrPercentage,
             }
         }
 
         impl ToComputedValue for SpecifiedValue {
             type ComputedValue = computed_value::T;
 
             #[inline]
-            fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+            fn to_computed_value(&self, context: &Context) -> computed_value::T {
                 computed_value::T {
                     horizontal: self.horizontal.to_computed_value(context),
                     vertical: self.vertical.to_computed_value(context),
                 }
             }
         }
 
         #[inline]
@@ -303,17 +303,17 @@
             }
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Explicit(ref size) => {
                     computed_value::T::Explicit(computed_value::ExplicitSize {
                         width: size.width.to_computed_value(context),
                         height: size.height.to_computed_value(context),
                     })
                 }
                 SpecifiedValue::Cover => computed_value::T::Cover,
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -57,17 +57,17 @@
         #[inline] pub fn get_initial_value() -> computed_value::T {
             Au::from_px(3)  // medium
         }
 
         impl ToComputedValue for SpecifiedValue {
             type ComputedValue = computed_value::T;
 
             #[inline]
-            fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+            fn to_computed_value(&self, context: &Context) -> computed_value::T {
                 self.0.to_computed_value(context)
             }
         }
     </%helpers:longhand>
 % endfor
 
 // FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage>
 % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]:
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -21,17 +21,17 @@
             list-item flex
             none
         """.split()
         if product == "gecko":
             values += "-moz-box -moz-inline-box".split()
         experimental_values = set("flex".split())
     %>
     pub use self::computed_value::T as SpecifiedValue;
-    use values::computed::{Context, ComputedValueAsSpecified};
+    use values::computed::ComputedValueAsSpecified;
 
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         #[allow(non_camel_case_types)]
         #[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
@@ -71,20 +71,19 @@
             % endfor
             _ => Err(())
         }
     }
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
 
     % if product == "servo":
-        fn cascade_property_custom<C: ComputedValues>(
-                                   _declaration: &PropertyDeclaration,
-                                   _inherited_style: &C,
-                                   context: &mut computed::Context<C>,
+        fn cascade_property_custom(_declaration: &PropertyDeclaration,
+                                   _inherited_style: &ComputedValues,
+                                   context: &mut computed::Context,
                                    _seen: &mut PropertyBitField,
                                    _cacheable: &mut bool,
                                    _error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
             longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
             longhands::_servo_text_decorations_in_effect::derive_from_display(context);
             longhands::_servo_under_display_none::derive_from_display(context);
         }
     % endif
@@ -100,17 +99,17 @@
                                   need_clone="True"
                                   gecko_ffi_name="mFloat">
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             let positioned = matches!(context.style().get_box().clone_position(),
                 longhands::position::SpecifiedValue::absolute |
                 longhands::position::SpecifiedValue::fixed);
             if positioned {
                 SpecifiedValue::none
             } else {
                 *self
             }
@@ -129,17 +128,17 @@
     pub use super::display::{SpecifiedValue, get_initial_value};
     pub use super::display::{parse};
 
     pub mod computed_value {
         pub type T = super::SpecifiedValue;
     }
 
     #[inline]
-    pub fn derive_from_display<Cx: TContext>(context: &mut Cx) {
+    pub fn derive_from_display(context: &mut Context) {
         let d = context.style().get_box().clone_display();
         context.mutate_style().mutate_box().set__servo_display_for_hypothetical_box(d);
     }
 
 </%helpers:longhand>
 
 <%helpers:longhand name="vertical-align"
                    animatable="True">
@@ -223,17 +222,17 @@
   }
   #[inline]
   pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline }
 
   impl ToComputedValue for SpecifiedValue {
       type ComputedValue = computed_value::T;
 
       #[inline]
-      fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+      fn to_computed_value(&self, context: &Context) -> computed_value::T {
           match *self {
               % for keyword in vertical_align_keywords:
                   SpecifiedValue::${to_rust_ident(keyword)} => {
                       computed_value::T::${to_rust_ident(keyword)}
                   }
               % endfor
               SpecifiedValue::LengthOrPercentage(value) =>
                   computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
@@ -282,17 +281,17 @@
       #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
       pub struct T(pub super::super::overflow_x::computed_value::T);
   }
 
   impl ToComputedValue for SpecifiedValue {
       type ComputedValue = computed_value::T;
 
       #[inline]
-      fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+      fn to_computed_value(&self, context: &Context) -> computed_value::T {
           computed_value::T(self.0.to_computed_value(context))
       }
   }
 
   pub fn get_initial_value() -> computed_value::T {
       computed_value::T(overflow_x::get_initial_value())
   }
 
@@ -311,17 +310,17 @@
     pub use self::computed_value::T as SpecifiedValue;
     pub use values::specified::Time as SingleSpecifiedValue;
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         use cssparser::ToCss;
         use std::fmt;
-        use values::computed::{TContext, ToComputedValue};
+        use values::computed::{Context, ToComputedValue};
 
         pub use values::computed::Time as SingleComputedValue;
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<SingleComputedValue>);
 
         impl ToCss for T {
@@ -492,17 +491,17 @@
 
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _: &Context) -> computed_value::T {
             (*self).clone()
         }
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(vec![get_initial_single_value()])
     }
@@ -618,17 +617,17 @@
 
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _: &Context) -> computed_value::T {
             (*self).clone()
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="transition-delay"
                    need_index="True"
                    animatable="False">
--- a/servo/components/style/properties/longhand/color.mako.rs
+++ b/servo/components/style/properties/longhand/color.mako.rs
@@ -10,17 +10,17 @@
     use cssparser::Color as CSSParserColor;
     use cssparser::RGBA;
     use values::specified::{CSSColor, CSSRGBA};
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _context: &Context) -> computed_value::T {
             self.parsed
         }
     }
 
     pub type SpecifiedValue = CSSRGBA;
     pub mod computed_value {
         use cssparser;
         pub type T = cssparser::RGBA;
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -58,17 +58,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Auto => computed_value::T(None),
                 SpecifiedValue::Specified(l) =>
                     computed_value::T(Some(l.to_computed_value(context)))
             }
         }
     }
 
@@ -124,17 +124,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Auto => computed_value::T(None),
                 SpecifiedValue::Specified(count) =>
                     computed_value::T(Some(count))
             }
         }
     }
 
@@ -204,17 +204,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Normal => computed_value::T(None),
                 SpecifiedValue::Specified(l) =>
                     computed_value::T(Some(l.to_computed_value(context)))
             }
         }
     }
 
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -93,17 +93,17 @@
             Ok(())
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T {
                 offset_x: self.offset_x.to_computed_value(context),
                 offset_y: self.offset_y.to_computed_value(context),
                 blur_radius: self.blur_radius.to_computed_value(context),
                 spread_radius: self.spread_radius.to_computed_value(context),
                 color: self.color
                             .as_ref()
                             .map(|color| color.parsed)
@@ -301,17 +301,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T(self.0.map(|value| computed_value::ClipRect {
                 top: value.top.to_computed_value(context),
                 right: value.right.map(|right| right.to_computed_value(context)),
                 bottom: value.bottom.map(|bottom| bottom.to_computed_value(context)),
                 left: value.left.to_computed_value(context),
             }))
         }
     }
@@ -593,17 +593,17 @@
             Ok(Token::Percentage(value)) => Ok(value.unit_value),
             _ => Err(())
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T{ filters: self.0.iter().map(|value| {
                 match *value {
                     SpecifiedFilter::Blur(factor) =>
                         computed_value::Filter::Blur(factor.to_computed_value(context)),
                     SpecifiedFilter::Brightness(factor) => computed_value::Filter::Brightness(factor),
                     SpecifiedFilter::Contrast(factor) => computed_value::Filter::Contrast(factor),
                     SpecifiedFilter::Grayscale(factor) => computed_value::Filter::Grayscale(factor),
                     SpecifiedFilter::HueRotate(factor) => computed_value::Filter::HueRotate(factor),
@@ -1059,17 +1059,17 @@
             Err(())
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             if self.0.is_empty() {
                 return computed_value::T(None)
             }
 
             let mut result = vec!();
             for operation in &self.0 {
                 match *operation {
                     SpecifiedOperation::Matrix(ref matrix) => {
@@ -1270,17 +1270,17 @@ pub fn parse_origin(_: &ParserContext, i
             depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
         })
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T {
                 horizontal: self.horizontal.to_computed_value(context),
                 vertical: self.vertical.to_computed_value(context),
                 depth: self.depth.to_computed_value(context),
             }
         }
     }
 </%helpers:longhand>
@@ -1356,17 +1356,17 @@ pub fn parse_origin(_: &ParserContext, i
             })
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T {
                 horizontal: self.horizontal.to_computed_value(context),
                 vertical: self.vertical.to_computed_value(context),
             }
         }
     }
 </%helpers:longhand>
 
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -215,17 +215,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T::Weight400  // normal
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 % for weight in range(100, 901, 100):
                     SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight},
                 % endfor
                 SpecifiedValue::Bolder => match context.inherited_style().get_font().clone_font_weight() {
                     computed_value::T::Weight100 => computed_value::T::Weight400,
                     computed_value::T::Weight200 => computed_value::T::Weight400,
                     computed_value::T::Weight300 => computed_value::T::Weight400,
@@ -283,17 +283,17 @@
     #[inline] pub fn get_initial_value() -> computed_value::T {
         Au::from_px(FONT_MEDIUM_PX)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match self.0 {
                 LengthOrPercentage::Length(Length::FontRelative(value)) => {
                     value.to_computed_value(context.inherited_style().get_font().clone_font_size(),
                                             context.style().root_font_size())
                 }
                 LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => {
                     value.to_computed_value(context.inherited_style().get_font().clone_font_size())
                 }
--- a/servo/components/style/properties/longhand/inherited_box.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_box.mako.rs
@@ -87,17 +87,17 @@
             _ => Err(())
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _: &Context) -> computed_value::T {
             *self
         }
     }
 </%helpers:longhand>
 
 // Used in the bottom-up flow construction traversal to avoid constructing flows for
 // descendants of nodes with `display: none`.
 <%helpers:longhand name="-servo-under-display-none"
@@ -126,18 +126,17 @@
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
             Ok(()) // Internal property
         }
     }
 
     #[inline]
-    pub fn derive_from_display<Cx: TContext>(context: &mut Cx) {
-        use properties::style_struct_traits::Box;
+    pub fn derive_from_display(context: &mut Context) {
         use super::display::computed_value::T as Display;
 
         if context.style().get_box().clone_display() == Display::none {
             context.mutate_style().mutate_inheritedbox()
                                   .set__servo_under_display_none(SpecifiedValue(true));
         }
     }
 </%helpers:longhand>
--- a/servo/components/style/properties/longhand/inherited_table.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_table.mako.rs
@@ -71,17 +71,17 @@
             self.vertical.to_css(dest)
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T {
                 horizontal: self.horizontal.to_computed_value(context),
                 vertical: self.vertical.to_computed_value(context),
             }
         }
     }
 
     pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -97,17 +97,17 @@
     }
      #[inline]
     pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Normal => computed_value::T::Normal,
                 % if product == "gecko":
                     SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
                 % endif
                 SpecifiedValue::Number(value) => computed_value::T::Number(value),
                 SpecifiedValue::LengthOrPercentage(value) => {
                     match value {
@@ -243,17 +243,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Normal => computed_value::T(None),
                 SpecifiedValue::Specified(l) =>
                     computed_value::T(Some(l.to_computed_value(context)))
             }
         }
     }
 
@@ -317,17 +317,17 @@
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Normal => computed_value::T(None),
                 SpecifiedValue::Specified(l) =>
                     computed_value::T(Some(l.to_computed_value(context)))
             }
         }
     }
 
@@ -369,17 +369,16 @@
                    derived_from="display text-decoration"
                    need_clone="True" products="servo"
                    animatable="False">
     use cssparser::{RGBA, ToCss};
     use std::fmt;
 
     use values:: NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
-    use properties::style_struct_traits::{Box, Color, Text};
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(Clone, PartialEq, Copy, Debug)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue {
         pub underline: Option<RGBA>,
@@ -402,25 +401,25 @@
     pub fn get_initial_value() -> computed_value::T {
         SpecifiedValue {
             underline: None,
             overline: None,
             line_through: None,
         }
     }
 
-    fn maybe<Cx: TContext>(flag: bool, context: &Cx) -> Option<RGBA> {
+    fn maybe(flag: bool, context: &Context) -> Option<RGBA> {
         if flag {
             Some(context.style().get_color().clone_color())
         } else {
             None
         }
     }
 
-    fn derive<Cx: TContext>(context: &Cx) -> computed_value::T {
+    fn derive(context: &Context) -> computed_value::T {
         // Start with no declarations if this is an atomic inline-level box; otherwise, start with the
         // declarations in effect and add in the text decorations that this block specifies.
         let mut result = match context.style().get_box().clone_display() {
             super::display::computed_value::T::inline_block |
             super::display::computed_value::T::inline_table => SpecifiedValue {
                 underline: None,
                 overline: None,
                 line_through: None,
@@ -434,23 +433,23 @@
                                 || result.overline.is_some(), context);
         result.line_through = maybe(context.style().get_text().has_line_through()
                                     || result.line_through.is_some(), context);
 
         result
     }
 
     #[inline]
-    pub fn derive_from_text_decoration<Cx: TContext>(context: &mut Cx) {
+    pub fn derive_from_text_decoration(context: &mut Context) {
         let derived = derive(context);
         context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived);
     }
 
     #[inline]
-    pub fn derive_from_display<Cx: TContext>(context: &mut Cx) {
+    pub fn derive_from_display(context: &mut Context) {
         let derived = derive(context);
         context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived);
     }
 </%helpers:longhand>
 
 <%helpers:single_keyword_computed name="white-space"
                                   values="normal pre nowrap pre-wrap pre-line"
                                   gecko_constant_prefix="NS_STYLE_WHITESPACE"
@@ -670,17 +669,17 @@
             blur_radius: lengths[2],
             color: color,
         })
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             computed_value::T(self.0.iter().map(|value| {
                 computed_value::TextShadow {
                     offset_x: value.offset_x.to_computed_value(context),
                     offset_y: value.offset_y.to_computed_value(context),
                     blur_radius: value.blur_radius.to_computed_value(context),
                     color: value.color
                                 .as_ref()
                                 .map(|color| color.parsed)
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -70,17 +70,17 @@
             }
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, _context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::None => computed_value::T(None),
                 SpecifiedValue::Url(ref url) => computed_value::T(Some(url.clone())),
             }
         }
     }
 
     pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
--- a/servo/components/style/properties/longhand/outline.mako.rs
+++ b/servo/components/style/properties/longhand/outline.mako.rs
@@ -58,17 +58,17 @@
         use app_units::Au;
         pub type T = Au;
     }
     pub use super::border_top_width::get_initial_value;
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
             self.0.to_computed_value(context)
         }
     }
 </%helpers:longhand>
 
 // The -moz-outline-radius-* properties are non-standard and not on a standards track.
 // TODO: Should they animate?
 % for corner in ["topleft", "topright", "bottomright", "bottomleft"]:
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -103,20 +103,19 @@
                 Ok(())
             }).is_ok() {
         }
 
         if !empty { Ok(result) } else { Err(()) }
     }
 
     % if product == "servo":
-        fn cascade_property_custom<C: ComputedValues>(
-                                   _declaration: &PropertyDeclaration,
-                                   _inherited_style: &C,
-                                   context: &mut computed::Context<C>,
+        fn cascade_property_custom(_declaration: &PropertyDeclaration,
+                                   _inherited_style: &ComputedValues,
+                                   context: &mut computed::Context,
                                    _seen: &mut PropertyBitField,
                                    _cacheable: &mut bool,
                                    _error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
                 longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context);
         }
     % endif
 </%helpers:longhand>
 
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -8,38 +8,38 @@
 // For example, Vec<&Foo> will be mangled as Vec&Foo>. To work around these issues, the code
 // can be escaped. In the above example, Vec<<&Foo> achieves the desired result of Vec<&Foo>.
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 use std::ascii::AsciiExt;
 use std::boxed::Box as StdBox;
 use std::collections::HashSet;
-use std::fmt;
-use std::fmt::{Debug, Write};
+use std::fmt::{self, Write};
 use std::sync::Arc;
 
 use app_units::Au;
-use cssparser::Color as CSSParserColor;
-use cssparser::{Parser, RGBA, AtRuleParser, DeclarationParser, Delimiter,
+#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
+use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter,
                 DeclarationListParser, parse_important, ToCss, TokenSerializationType};
 use error_reporting::ParseErrorReporter;
 use url::Url;
-use euclid::side_offsets::SideOffsets2D;
+#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
 use euclid::size::Size2D;
 use string_cache::Atom;
 use computed_values;
-use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode};
+#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
+use logical_geometry::WritingMode;
 use parser::{ParserContext, ParserContextExtraData, log_css_error};
 use selectors::matching::DeclarationBlock;
 use stylesheets::Origin;
 use values::LocalToCss;
 use values::HasViewportPercentage;
-use values::computed::{self, TContext, ToComputedValue};
-use values::specified::BorderStyle;
+use values::computed::{self, ToComputedValue};
+#[cfg(feature = "servo")] use values::specified::BorderStyle;
 
 use self::property_bit_field::PropertyBitField;
 
 <%!
     from data import Method, Keyword, to_rust_ident
 %>
 
 pub mod longhands {
@@ -1077,317 +1077,264 @@ impl PropertyDeclaration {
                 % endif
             }
             % endfor
             PropertyDeclaration::Custom(..) => false,
         }
     }
 }
 
-pub mod style_struct_traits {
-    use super::longhands;
-    use std::fmt::Debug;
-
-    % for style_struct in data.active_style_structs():
-        pub trait ${style_struct.trait_name}: Debug + Clone {
-            % for longhand in style_struct.longhands:
-                #[allow(non_snake_case)]
-                fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T);
-                #[allow(non_snake_case)]
-                fn copy_${longhand.ident}_from(&mut self, other: &Self);
-                % if longhand.need_clone:
-                    #[allow(non_snake_case)]
-                    fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T;
-                % endif
-                % if longhand.need_index:
-                    #[allow(non_snake_case)]
-                    fn ${longhand.ident}_count(&self) -> usize;
-
-                    #[allow(non_snake_case)]
-                    fn ${longhand.ident}_at(&self, index: usize)
-                        -> longhands::${longhand.ident}::computed_value::SingleComputedValue;
-
-                    #[allow(non_snake_case)]
-                    #[inline]
-                    fn ${longhand.ident}_iter<'a>(&'a self)
-                        -> ${longhand.camel_case}Iter<'a, Self> {
-                        ${longhand.camel_case}Iter {
-                            style_struct: self,
-                            current: 0,
-                            max: self.${longhand.ident}_count(),
-                        }
-                    }
+#[cfg(feature = "gecko")]
+pub use gecko_properties::style_structs;
 
-                    #[allow(non_snake_case)]
-                    #[inline]
-                    fn ${longhand.ident}_mod(&self, index: usize)
-                        -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
-                        self.${longhand.ident}_at(index % self.${longhand.ident}_count())
-                    }
-                % endif
-            % endfor
-            % for additional in style_struct.additional_methods:
-                #[allow(non_snake_case)]
-                ${additional.declare()}
-            % endfor
-        }
-
-        % for longhand in style_struct.longhands:
-            % if longhand.need_index:
-                pub struct ${longhand.camel_case}Iter<'a, S: ${style_struct.trait_name} + 'static> {
-                    style_struct: &'a S,
-                    current: usize,
-                    max: usize,
-                }
-
-                impl<'a, S: ${style_struct.trait_name} + 'static> Iterator for ${longhand.camel_case}Iter<'a, S> {
-                    type Item = longhands::${longhand.ident}::computed_value::SingleComputedValue;
-
-                    fn next(&mut self) -> Option<Self::Item> {
-                        self.current += 1;
-                        if self.current <= self.max {
-                            Some(self.style_struct.${longhand.ident}_at(self.current - 1))
-                        } else {
-                            None
-                        }
-                    }
-                }
-            % endif
-        % endfor
-    % endfor
-}
-
+#[cfg(feature = "servo")]
 pub mod style_structs {
     use fnv::FnvHasher;
     use super::longhands;
     use std::hash::{Hash, Hasher};
 
     % for style_struct in data.active_style_structs():
-        % if style_struct.trait_name == "Font":
+        % if style_struct.name == "Font":
         #[derive(Clone, Debug)]
-        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         % else:
         #[derive(PartialEq, Clone, Debug)]
+        % endif
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-        % endif
-        pub struct ${style_struct.servo_struct_name} {
+        pub struct ${style_struct.name} {
             % for longhand in style_struct.longhands:
                 pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
             % endfor
-            % if style_struct.trait_name == "Font":
+            % if style_struct.name == "Font":
                 pub hash: u64,
             % endif
         }
-        % if style_struct.trait_name == "Font":
+        % if style_struct.name == "Font":
 
-        impl PartialEq for ${style_struct.servo_struct_name} {
-            fn eq(&self, other: &${style_struct.servo_struct_name}) -> bool {
+        impl PartialEq for ${style_struct.name} {
+            fn eq(&self, other: &${style_struct.name}) -> bool {
                 self.hash == other.hash
                 % for longhand in style_struct.longhands:
                     && self.${longhand.ident} == other.${longhand.ident}
                 % endfor
             }
         }
         % endif
 
-        impl super::style_struct_traits::${style_struct.trait_name} for ${style_struct.servo_struct_name} {
+        impl ${style_struct.name} {
             % for longhand in style_struct.longhands:
+                #[allow(non_snake_case)]
                 #[inline]
-                fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
+                pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
                     self.${longhand.ident} = v;
                 }
+                #[allow(non_snake_case)]
                 #[inline]
-                fn copy_${longhand.ident}_from(&mut self, other: &Self) {
+                pub fn copy_${longhand.ident}_from(&mut self, other: &Self) {
                     self.${longhand.ident} = other.${longhand.ident}.clone();
                 }
                 % if longhand.need_clone:
+                    #[allow(non_snake_case)]
                     #[inline]
-                    fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
+                    pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
                         self.${longhand.ident}.clone()
                     }
                 % endif
 
                 % if longhand.need_index:
-                    fn ${longhand.ident}_count(&self) -> usize {
+                    #[allow(non_snake_case)]
+                    pub fn ${longhand.ident}_count(&self) -> usize {
                         self.${longhand.ident}.0.len()
                     }
 
-                    fn ${longhand.ident}_at(&self, index: usize)
+                    #[allow(non_snake_case)]
+                    pub fn ${longhand.ident}_at(&self, index: usize)
                         -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
                         self.${longhand.ident}.0[index].clone()
                     }
                 % endif
             % endfor
-            % if style_struct.trait_name == "Border":
+            % if style_struct.name == "Border":
                 % for side in ["top", "right", "bottom", "left"]:
-                    fn border_${side}_has_nonzero_width(&self) -> bool {
+                    #[allow(non_snake_case)]
+                    pub fn border_${side}_has_nonzero_width(&self) -> bool {
                         self.border_${side}_width != ::app_units::Au(0)
                     }
                 % endfor
-            % elif style_struct.trait_name == "Font":
-                fn compute_font_hash(&mut self) {
+            % elif style_struct.name == "Font":
+                pub fn compute_font_hash(&mut self) {
                     // Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`.
                     let mut hasher: FnvHasher = Default::default();
                     hasher.write_u16(self.font_weight as u16);
                     self.font_stretch.hash(&mut hasher);
                     self.font_family.hash(&mut hasher);
                     self.hash = hasher.finish()
                 }
-            % elif style_struct.trait_name == "Outline":
+            % elif style_struct.name == "Outline":
                 #[inline]
-                fn outline_has_nonzero_width(&self) -> bool {
+                pub fn outline_has_nonzero_width(&self) -> bool {
                     self.outline_width != ::app_units::Au(0)
                 }
-            % elif style_struct.trait_name == "Text":
+            % elif style_struct.name == "Text":
                 <% text_decoration_field = 'text_decoration' if product == 'servo' else 'text_decoration_line' %>
                 #[inline]
-                fn has_underline(&self) -> bool {
+                pub fn has_underline(&self) -> bool {
                     self.${text_decoration_field}.underline
                 }
                 #[inline]
-                fn has_overline(&self) -> bool {
+                pub fn has_overline(&self) -> bool {
                     self.${text_decoration_field}.overline
                 }
                 #[inline]
-                fn has_line_through(&self) -> bool {
+                pub fn has_line_through(&self) -> bool {
                     self.${text_decoration_field}.line_through
                 }
             % endif
         }
 
     % endfor
 }
 
-pub trait ComputedValues : Debug + Clone + Send + Sync + 'static {
-    % for style_struct in data.active_style_structs():
-        type Concrete${style_struct.trait_name}: style_struct_traits::${style_struct.trait_name};
-    % endfor
+% for style_struct in data.active_style_structs():
+    impl style_structs::${style_struct.name} {
+        % for longhand in style_struct.longhands:
+            % if longhand.need_index:
+                #[allow(non_snake_case)]
+                #[inline]
+                pub fn ${longhand.ident}_iter(&self) -> ${longhand.camel_case}Iter {
+                    ${longhand.camel_case}Iter {
+                        style_struct: self,
+                        current: 0,
+                        max: self.${longhand.ident}_count(),
+                    }
+                }
+
+                #[allow(non_snake_case)]
+                #[inline]
+                pub fn ${longhand.ident}_mod(&self, index: usize)
+                    -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
+                    self.${longhand.ident}_at(index % self.${longhand.ident}_count())
+                }
+            % endif
+        % endfor
+    }
 
-        fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
-               shareable: bool,
-               writing_mode: WritingMode,
-               root_font_size: Au,
-        % for style_struct in data.active_style_structs():
-               ${style_struct.ident}: Arc<Self::Concrete${style_struct.trait_name}>,
-        % endfor
-        ) -> Self;
+    % for longhand in style_struct.longhands:
+        % if longhand.need_index:
+            pub struct ${longhand.camel_case}Iter<'a> {
+                style_struct: &'a style_structs::${style_struct.name},
+                current: usize,
+                max: usize,
+            }
+
+            impl<'a> Iterator for ${longhand.camel_case}Iter<'a> {
+                type Item = longhands::${longhand.ident}::computed_value::SingleComputedValue;
 
-        fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self>;
+                fn next(&mut self) -> Option<Self::Item> {
+                    self.current += 1;
+                    if self.current <= self.max {
+                        Some(self.style_struct.${longhand.ident}_at(self.current - 1))
+                    } else {
+                        None
+                    }
+                }
+            }
+        % endif
+    % endfor
+% endfor
 
-        fn initial_values() -> &'static Self;
+
+#[cfg(feature = "gecko")]
+pub use gecko_properties::ComputedValues;
 
-        fn do_cascade_property<F: FnOnce(&[CascadePropertyFn<Self>])>(f: F);
+#[cfg(feature = "servo")]
+pub type ServoComputedValues = ComputedValues;
 
+#[cfg(feature = "servo")]
+#[cfg_attr(feature = "servo", derive(Clone, Debug, HeapSizeOf))]
+pub struct ComputedValues {
     % for style_struct in data.active_style_structs():
-        fn clone_${style_struct.trait_name_lower}(&self) ->
-            Arc<Self::Concrete${style_struct.trait_name}>;
-        fn get_${style_struct.trait_name_lower}<'a>(&'a self) ->
-            &'a Self::Concrete${style_struct.trait_name};
-        fn mutate_${style_struct.trait_name_lower}<'a>(&'a mut self) ->
-            &'a mut Self::Concrete${style_struct.trait_name};
-    % endfor
-
-    fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>>;
-    fn root_font_size(&self) -> Au;
-    fn set_root_font_size(&mut self, size: Au);
-    fn set_writing_mode(&mut self, mode: WritingMode);
-    fn is_multicol(&self) -> bool;
-}
-
-#[derive(Clone, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct ServoComputedValues {
-    % for style_struct in data.active_style_structs():
-        ${style_struct.ident}: Arc<style_structs::${style_struct.servo_struct_name}>,
+        ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
     custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
     shareable: bool,
     pub writing_mode: WritingMode,
     pub root_font_size: Au,
 }
 
-impl ComputedValues for ServoComputedValues {
-    % for style_struct in data.active_style_structs():
-        type Concrete${style_struct.trait_name} = style_structs::${style_struct.servo_struct_name};
-    % endfor
+#[cfg(feature = "servo")]
+impl ComputedValues {
+    pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
+           shareable: bool,
+           writing_mode: WritingMode,
+           root_font_size: Au,
+        % for style_struct in data.active_style_structs():
+           ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
+        % endfor
+    ) -> Self {
+        ComputedValues {
+            custom_properties: custom_properties,
+            shareable: shareable,
+            writing_mode: writing_mode,
+            root_font_size: root_font_size,
+        % for style_struct in data.active_style_structs():
+            ${style_struct.ident}: ${style_struct.ident},
+        % endfor
+        }
+    }
 
-        fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
-               shareable: bool,
-               writing_mode: WritingMode,
-               root_font_size: Au,
-            % for style_struct in data.active_style_structs():
-               ${style_struct.ident}: Arc<style_structs::${style_struct.servo_struct_name}>,
-            % endfor
-        ) -> Self {
-            ServoComputedValues {
-                custom_properties: custom_properties,
-                shareable: shareable,
-                writing_mode: writing_mode,
-                root_font_size: root_font_size,
-            % for style_struct in data.active_style_structs():
-                ${style_struct.ident}: ${style_struct.ident},
-            % endfor
-            }
-        }
+    pub fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
+        // Text nodes get a copy of the parent style. Inheriting all non-
+        // inherited properties into the text node is odd from a CSS
+        // perspective, but makes fragment construction easier (by making
+        // properties like vertical-align on fragments have values that
+        // match the parent element). This is an implementation detail of
+        // Servo layout that is not central to how fragment construction
+        // works, but would be difficult to change. (Text node style is
+        // also not visible to script.)
+        parent.clone()
+    }
 
-        fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
-            // Text nodes get a copy of the parent style. Inheriting all non-
-            // inherited properties into the text node is odd from a CSS
-            // perspective, but makes fragment construction easier (by making
-            // properties like vertical-align on fragments have values that
-            // match the parent element). This is an implementation detail of
-            // Servo layout that is not central to how fragment construction
-            // works, but would be difficult to change. (Text node style is
-            // also not visible to script.)
-            parent.clone()
-        }
+    pub fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
 
-        fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
-
-        #[inline]
-        fn do_cascade_property<F: FnOnce(&[CascadePropertyFn<Self>])>(f: F) {
-            f(&CASCADE_PROPERTY)
-        }
+    #[inline]
+    pub fn do_cascade_property<F: FnOnce(&[CascadePropertyFn])>(f: F) {
+        f(&CASCADE_PROPERTY)
+    }
 
     % for style_struct in data.active_style_structs():
         #[inline]
-        fn clone_${style_struct.trait_name_lower}(&self) ->
-            Arc<Self::Concrete${style_struct.trait_name}> {
+        pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
                 self.${style_struct.ident}.clone()
             }
         #[inline]
-        fn get_${style_struct.trait_name_lower}<'a>(&'a self) ->
-            &'a Self::Concrete${style_struct.trait_name} {
-                &self.${style_struct.ident}
-            }
+        pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
+            &self.${style_struct.ident}
+        }
         #[inline]
-        fn mutate_${style_struct.trait_name_lower}<'a>(&'a mut self) ->
-            &'a mut Self::Concrete${style_struct.trait_name} {
-                Arc::make_mut(&mut self.${style_struct.ident})
-            }
+        pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
+            Arc::make_mut(&mut self.${style_struct.ident})
+        }
     % endfor
 
     // Cloning the Arc here is fine because it only happens in the case where we have custom
     // properties, and those are both rare and expensive.
-    fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
+    pub fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
         self.custom_properties.as_ref().map(|x| x.clone())
     }
 
-    fn root_font_size(&self) -> Au { self.root_font_size }
-    fn set_root_font_size(&mut self, size: Au) { self.root_font_size = size }
-    fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }
+    pub fn root_font_size(&self) -> Au { self.root_font_size }
+    pub fn set_root_font_size(&mut self, size: Au) { self.root_font_size = size }
+    pub fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }
 
     #[inline]
-    fn is_multicol(&self) -> bool {
+    pub fn is_multicol(&self) -> bool {
         let style = self.get_column();
         style.column_count.0.is_some() || style.column_width.0.is_some()
     }
-}
 
-impl ServoComputedValues {
     /// Resolves the currentColor keyword.
     /// Any color value form computed values (except for the 'color' property itself)
     /// should go through this method.
     ///
     /// Usage example:
     /// let top_color = style.resolve_color(style.Border.border_top_color);
     #[inline]
     pub fn resolve_color(&self, color: CSSParserColor) -> RGBA {
@@ -1478,17 +1425,17 @@ impl ServoComputedValues {
             position_style.top,
             position_style.right,
             position_style.bottom,
             position_style.left,
         ))
     }
 
     #[inline]
-    pub fn get_font_arc(&self) -> Arc<style_structs::ServoFont> {
+    pub fn get_font_arc(&self) -> Arc<style_structs::Font> {
         self.font.clone()
     }
 
     // http://dev.w3.org/csswg/css-transforms/#grouping-property-values
     pub fn get_used_transform_style(&self) -> computed_values::transform_style::T {
         use computed_values::mix_blend_mode;
         use computed_values::transform_style;
 
@@ -1561,17 +1508,17 @@ impl ServoComputedValues {
                 Ok(value.to_css_string())
             }
         }
     }
 }
 
 
 /// Return a WritingMode bitflags from the relevant CSS properties.
-pub fn get_writing_mode<S: style_struct_traits::InheritedBox>(inheritedbox_style: &S) -> WritingMode {
+pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode {
     use logical_geometry;
     let mut flags = WritingMode::empty();
     match inheritedbox_style.clone_direction() {
         computed_values::direction::T::ltr => {},
         computed_values::direction::T::rtl => {
             flags.insert(logical_geometry::FLAG_RTL);
         },
     }
@@ -1602,110 +1549,119 @@ pub fn get_writing_mode<S: style_struct_
                 flags.insert(logical_geometry::FLAG_SIDEWAYS_LEFT);
             }
         },
     }
     flags
 }
 
 
-/// The initial values for all style structs as defined by the specification.
-lazy_static! {
-    pub static ref INITIAL_SERVO_VALUES: ServoComputedValues = ServoComputedValues {
-        % for style_struct in data.active_style_structs():
-            ${style_struct.ident}: Arc::new(style_structs::${style_struct.servo_struct_name} {
-                % for longhand in style_struct.longhands:
-                    ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
-                % endfor
-                % if style_struct.trait_name == "Font":
-                    hash: 0,
-                % endif
-            }),
-        % endfor
-        custom_properties: None,
-        shareable: true,
-        writing_mode: WritingMode::empty(),
-        root_font_size: longhands::font_size::get_initial_value(),
-    };
+#[cfg(feature = "servo")]
+pub use self::lazy_static_module::INITIAL_SERVO_VALUES;
+
+// Use a module to work around #[cfg] on lazy_static! not being applied to every generated item.
+#[cfg(feature = "servo")]
+mod lazy_static_module {
+    use logical_geometry::WritingMode;
+    use std::sync::Arc;
+    use super::{ComputedValues, longhands, style_structs};
+
+    /// The initial values for all style structs as defined by the specification.
+    lazy_static! {
+        pub static ref INITIAL_SERVO_VALUES: ComputedValues = ComputedValues {
+            % for style_struct in data.active_style_structs():
+                ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
+                    % for longhand in style_struct.longhands:
+                        ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
+                    % endfor
+                    % if style_struct.name == "Font":
+                        hash: 0,
+                    % endif
+                }),
+            % endfor
+            custom_properties: None,
+            shareable: true,
+            writing_mode: WritingMode::empty(),
+            root_font_size: longhands::font_size::get_initial_value(),
+        };
+    }
 }
 
-
 /// Fast path for the function below. Only computes new inherited styles.
 #[allow(unused_mut, unused_imports)]
-fn cascade_with_cached_declarations<C: ComputedValues>(
+fn cascade_with_cached_declarations(
         viewport_size: Size2D<Au>,
         applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
         shareable: bool,
-        parent_style: &C,
-        cached_style: &C,
+        parent_style: &ComputedValues,
+        cached_style: &ComputedValues,
         custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
         mut error_reporter: StdBox<ParseErrorReporter + Send>)
-        -> C {
+        -> ComputedValues {
     let mut context = computed::Context {
         is_root_element: false,
         viewport_size: viewport_size,
         inherited_style: parent_style,
-        style: C::new(
+        style: ComputedValues::new(
             custom_properties,
             shareable,
             WritingMode::empty(),
             parent_style.root_font_size(),
             % for style_struct in data.active_style_structs():
                 % if style_struct.inherited:
                     parent_style
                 % else:
                     cached_style
                 % endif
-                    .clone_${style_struct.trait_name_lower}(),
+                    .clone_${style_struct.name_lower}(),
             % endfor
         ),
     };
     let mut seen = PropertyBitField::new();
     // Declaration blocks are stored in increasing precedence order,
     // we want them in decreasing order here.
     for sub_list in applicable_declarations.iter().rev() {
         // Declarations are already stored in reverse order.
         for declaration in sub_list.declarations.iter() {
             match *declaration {
                 % for style_struct in data.active_style_structs():
                     % for property in style_struct.longhands:
                         % if not property.derived_from:
                             PropertyDeclaration::${property.camel_case}(ref
                                     ${'_' if not style_struct.inherited else ''}declared_value)
                                     => {
-                                    use properties::style_struct_traits::${style_struct.trait_name};
                                 % if style_struct.inherited:
                                     if seen.get_${property.ident}() {
                                         continue
                                     }
                                     seen.set_${property.ident}();
                                     let custom_props = context.style().custom_properties();
                                     substitute_variables_${property.ident}(
                                         declared_value, &custom_props,
                                         |value| match *value {
                                             DeclaredValue::Value(ref specified_value)
                                             => {
                                                 let computed = specified_value.to_computed_value(&context);
-                                                context.mutate_style().mutate_${style_struct.trait_name_lower}()
+                                                context.mutate_style().mutate_${style_struct.name_lower}()
                                                        .set_${property.ident}(computed);
                                             },
                                             DeclaredValue::Initial
                                             => {
                                                 // FIXME(bholley): We may want set_X_to_initial_value() here.
                                                 let initial = longhands::${property.ident}::get_initial_value();
-                                                context.mutate_style().mutate_${style_struct.trait_name_lower}()
+                                                context.mutate_style().mutate_${style_struct.name_lower}()
                                                        .set_${property.ident}(initial);
                                             },
                                             DeclaredValue::Inherit => {
                                                 // This is a bit slow, but this is rare so it shouldn't
                                                 // matter.
                                                 //
                                                 // FIXME: is it still?
                                                 let inherited_struct = parent_style.get_${style_struct.ident}();
-                                                context.mutate_style().mutate_${style_struct.trait_name_lower}()
+                                                context.mutate_style().mutate_${style_struct.name_lower}()
                                                        .copy_${property.ident}_from(inherited_struct);
                                             }
                                             DeclaredValue::WithVariables { .. } => unreachable!()
                                         }, &mut error_reporter
                                     );
                                 % endif
 
                                 % if property.name in data.derived_longhands:
@@ -1724,32 +1680,32 @@ fn cascade_with_cached_declarations<C: C
                 % endfor
                 PropertyDeclaration::Custom(..) => {}
             }
         }
     }
 
     if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() ||
             seen.get_font_family() {
-        use properties::style_struct_traits::Font;
         context.mutate_style().mutate_font().compute_font_hash();
     }
 
     context.style
 }
 
-pub type CascadePropertyFn<C /*: ComputedValues */> =
+pub type CascadePropertyFn =
     extern "Rust" fn(declaration: &PropertyDeclaration,
-                     inherited_style: &C,
-                     context: &mut computed::Context<C>,
+                     inherited_style: &ComputedValues,
+                     context: &mut computed::Context,
                      seen: &mut PropertyBitField,
                      cacheable: &mut bool,
                      error_reporter: &mut StdBox<ParseErrorReporter + Send>);
 
-static CASCADE_PROPERTY: [CascadePropertyFn<ServoComputedValues>; ${len(data.longhands)}] = [
+#[cfg(feature = "servo")]
+static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
     % for property in data.longhands:
         longhands::${property.ident}::cascade_property,
     % endfor
 ];
 
 /// Performs the CSS cascade, computing new styles for an element from its parent style and
 /// optionally a cached related style. The arguments are:
 ///
@@ -1763,26 +1719,24 @@ static CASCADE_PROPERTY: [CascadePropert
 ///   * `parent_style`: The parent style, if applicable; if `None`, this is the root node.
 ///
 ///   * `cached_style`: If present, cascading is short-circuited for everything but inherited
 ///     values and these values are used instead. Obviously, you must be careful when supplying
 ///     this that it is safe to only provide inherited declarations. If `parent_style` is `None`,
 ///     this is ignored.
 ///
 /// Returns the computed values and a boolean indicating whether the result is cacheable.
-pub fn cascade<C: ComputedValues>(
-               viewport_size: Size2D<Au>,
+pub fn cascade(viewport_size: Size2D<Au>,
                applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
                shareable: bool,
-               parent_style: Option<<&C>,
-               cached_style: Option<<&C>,
+               parent_style: Option<<&ComputedValues>,
+               cached_style: Option<<&ComputedValues>,
                mut error_reporter: StdBox<ParseErrorReporter + Send>)
-               -> (C, bool) {
-    use properties::style_struct_traits::{Border, Box, Font, Outline};
-    let initial_values = C::initial_values();
+               -> (ComputedValues, bool) {
+    let initial_values = ComputedValues::initial_values();
     let (is_root_element, inherited_style) = match parent_style {
         Some(parent_style) => (false, parent_style),
         None => (true, initial_values),
     };
 
     let inherited_custom_properties = inherited_style.custom_properties();
     let mut custom_properties = None;
     let mut seen_custom = HashSet::new();
@@ -1812,42 +1766,42 @@ pub fn cascade<C: ComputedValues>(
                                                      error_reporter);
         return (style, false)
     }
 
     let mut context = computed::Context {
         is_root_element: is_root_element,
         viewport_size: viewport_size,
         inherited_style: inherited_style,
-        style: C::new(
+        style: ComputedValues::new(
             custom_properties,
             shareable,
             WritingMode::empty(),
             inherited_style.root_font_size(),
             % for style_struct in data.active_style_structs():
             % if style_struct.inherited:
             inherited_style
             % else:
             initial_values
             % endif
-                .clone_${style_struct.trait_name_lower}(),
+                .clone_${style_struct.name_lower}(),
             % endfor
         ),
     };
 
     // Set computed values, overwriting earlier declarations for the same property.
     let mut cacheable = true;
     let mut seen = PropertyBitField::new();
     // Declaration blocks are stored in increasing precedence order, we want them in decreasing
     // order here.
     //
     // We could (and used to) use a pattern match here, but that bloats this function to over 100K
     // of compiled code! To improve i-cache behavior, we outline the individual functions and use
     // virtual dispatch instead.
-    C::do_cascade_property(|cascade_property| {
+    ComputedValues::do_cascade_property(|cascade_property| {
         % for category_to_cascade_now in ["early", "other"]:
             for sub_list in applicable_declarations.iter().rev() {
                 // Declarations are already stored in reverse order.
                 for declaration in sub_list.declarations.iter() {
                     if let PropertyDeclaration::Custom(..) = *declaration {
                         continue
                     }
                     // The computed value of some properties depends on the (sometimes computed)
@@ -1935,17 +1889,16 @@ pub fn cascade<C: ComputedValues>(
                 style.mutate_box().set_overflow_y(overflow_y::T(overflow::auto));
             }
             _ => {}
         }
     }
 
     % if "align-items" in data.longhands_by_name:
     {
-        use self::style_struct_traits::Position;
         use computed_values::align_self::T as align_self;
         use computed_values::align_items::T as align_items;
         if style.get_position().clone_align_self() == computed_values::align_self::T::auto && !positioned {
             let self_align =
                 match context.inherited_style.get_position().clone_align_items() {
                     align_items::stretch => align_self::stretch,
                     align_items::baseline => align_self::baseline,
                     align_items::flex_start => align_self::flex_start,
@@ -1974,26 +1927,26 @@ pub fn cascade<C: ComputedValues>(
 
     if is_root_element {
         let s = style.get_font().clone_font_size();
         style.set_root_font_size(s);
     }
 
     if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() ||
             seen.get_font_family() {
-        use properties::style_struct_traits::Font;
         style.mutate_font().compute_font_hash();
     }
 
     let mode = get_writing_mode(style.get_inheritedbox());
     style.set_writing_mode(mode);
     (style, cacheable)
 }
 
-pub fn modify_style_for_anonymous_flow(style: &mut Arc<ServoComputedValues>,
+#[cfg(feature = "servo")]
+pub fn modify_style_for_anonymous_flow(style: &mut Arc<ComputedValues>,
                                       new_display_value: longhands::display::computed_value::T) {
     // The 'align-self' property needs some special treatment since
     // its value depends on the 'align-items' value of its parent.
     % if "align-items" in data.longhands_by_name:
         use computed_values::align_self::T as align_self;
         use computed_values::align_items::T as align_items;
         let self_align =
             match style.position.align_items {
@@ -2003,17 +1956,17 @@ pub fn modify_style_for_anonymous_flow(s
                 align_items::flex_end => align_self::flex_end,
                 align_items::center => align_self::center,
             };
     % endif
     let inital_values = &*INITIAL_SERVO_VALUES;
     let mut style = Arc::make_mut(style);
     % for style_struct in data.active_style_structs():
     % if not style_struct.inherited:
-        style.${style_struct.ident} = inital_values.clone_${style_struct.trait_name_lower}();
+        style.${style_struct.ident} = inital_values.clone_${style_struct.name_lower}();
     % endif
     % endfor
     % if "align-items" in data.longhands_by_name:
        let position = Arc::make_mut(&mut style.position);
        position.align_self = self_align;
     % endif
     if new_display_value != longhands::display::computed_value::T::inline {
         let new_box = Arc::make_mut(&mut style.box_);
@@ -2030,18 +1983,19 @@ pub fn modify_style_for_anonymous_flow(s
 }
 
 /// Alters the given style to accommodate replaced content. This is called in flow construction. It
 /// handles cases like `<div style="position: absolute">foo bar baz</div>` (in which `foo`, `bar`,
 /// and `baz` must not be absolutely-positioned) and cases like `<sup>Foo</sup>` (in which the
 /// `vertical-align: top` style of `sup` must not propagate down into `Foo`).
 ///
 /// FIXME(#5625, pcwalton): It would probably be cleaner and faster to do this in the cascade.
+#[cfg(feature = "servo")]
 #[inline]
-pub fn modify_style_for_replaced_content(style: &mut Arc<ServoComputedValues>) {
+pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
     // Reset `position` to handle cases like `<div style="position: absolute">foo bar baz</div>`.
     if style.box_.display != longhands::display::computed_value::T::inline {
         let mut style = Arc::make_mut(style);
         Arc::make_mut(&mut style.box_).display = longhands::display::computed_value::T::inline;
         Arc::make_mut(&mut style.box_).position =
             longhands::position::computed_value::T::static_;
     }
 
@@ -2066,21 +2020,22 @@ pub fn modify_style_for_replaced_content
     }
 }
 
 /// Adjusts borders as appropriate to account for a fragment's status as the first or last fragment
 /// within the range of an element.
 ///
 /// Specifically, this function sets border widths to zero on the sides for which the fragment is
 /// not outermost.
+#[cfg(feature = "servo")]
 #[inline]
-pub fn modify_border_style_for_inline_sides(style: &mut Arc<ServoComputedValues>,
+pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
                                             is_first_fragment_of_element: bool,
                                             is_last_fragment_of_element: bool) {
-    fn modify_side(style: &mut Arc<ServoComputedValues>, side: PhysicalSide) {
+    fn modify_side(style: &mut Arc<ComputedValues>, side: PhysicalSide) {
         {
             let border = &style.border;
             let current_style = match side {
                 PhysicalSide::Left =>   (border.border_left_width,   border.border_left_style),
                 PhysicalSide::Right =>  (border.border_right_width,  border.border_right_style),
                 PhysicalSide::Top =>    (border.border_top_width,    border.border_top_style),
                 PhysicalSide::Bottom => (border.border_bottom_width, border.border_bottom_style),
             };
@@ -2117,40 +2072,43 @@ pub fn modify_border_style_for_inline_si
 
     if !is_last_fragment_of_element {
         let side = style.writing_mode.inline_end_physical_side();
         modify_side(style, side)
     }
 }
 
 /// Adjusts the display and position properties as appropriate for an anonymous table object.
+#[cfg(feature = "servo")]
 #[inline]
 pub fn modify_style_for_anonymous_table_object(
-        style: &mut Arc<ServoComputedValues>,
+        style: &mut Arc<ComputedValues>,
         new_display_value: longhands::display::computed_value::T) {
     let mut style = Arc::make_mut(style);
     let box_style = Arc::make_mut(&mut style.box_);
     box_style.display = new_display_value;
     box_style.position = longhands::position::computed_value::T::static_;
 }
 
 /// Adjusts the `position` property as necessary for the outer fragment wrapper of an inline-block.
+#[cfg(feature = "servo")]
 #[inline]
-pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ServoComputedValues>) {
+pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ComputedValues>) {
     let mut style = Arc::make_mut(style);
     let box_style = Arc::make_mut(&mut style.box_);
     box_style.position = longhands::position::computed_value::T::static_
 }
 
 /// Adjusts the `position` and `padding` properties as necessary to account for text.
 ///
 /// Text is never directly relatively positioned; it's always contained within an element that is
 /// itself relatively positioned.
+#[cfg(feature = "servo")]
 #[inline]
-pub fn modify_style_for_text(style: &mut Arc<ServoComputedValues>) {
+pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
     if style.box_.position == longhands::position::computed_value::T::relative {
         // We leave the `position` property set to `relative` so that we'll still establish a
         // containing block if needed. But we reset all position offsets to `auto`.
         let mut style = Arc::make_mut(style);
         let mut position = Arc::make_mut(&mut style.position);
         position.top = computed::LengthOrPercentageOrAuto::Auto;
         position.right = computed::LengthOrPercentageOrAuto::Auto;
         position.bottom = computed::LengthOrPercentageOrAuto::Auto;
@@ -2175,32 +2133,34 @@ pub fn modify_style_for_text(style: &mut
         effects.opacity = 1.0;
     }
 }
 
 /// Adjusts the `margin` property as necessary to account for the text of an `input` element.
 ///
 /// Margins apply to the `input` element itself, so including them in the text will cause them to
 /// be double-counted.
-pub fn modify_style_for_input_text(style: &mut Arc<ServoComputedValues>) {
+#[cfg(feature = "servo")]
+pub fn modify_style_for_input_text(style: &mut Arc<ComputedValues>) {
     let mut style = Arc::make_mut(style);
     let margin_style = Arc::make_mut(&mut style.margin);
     margin_style.margin_top = computed::LengthOrPercentageOrAuto::Length(Au(0));
     margin_style.margin_right = computed::LengthOrPercentageOrAuto::Length(Au(0));
     margin_style.margin_bottom = computed::LengthOrPercentageOrAuto::Length(Au(0));
     margin_style.margin_left = computed::LengthOrPercentageOrAuto::Length(Au(0));
 
     // whitespace inside text input should not be collapsed
     let inherited_text = Arc::make_mut(&mut style.inheritedtext);
     inherited_text.white_space = longhands::white_space::computed_value::T::pre;
 }
 
 /// Adjusts the `clip` property so that an inline absolute hypothetical fragment doesn't clip its
 /// children.
-pub fn modify_style_for_inline_absolute_hypothetical_fragment(style: &mut Arc<ServoComputedValues>) {
+#[cfg(feature = "servo")]
+pub fn modify_style_for_inline_absolute_hypothetical_fragment(style: &mut Arc<ComputedValues>) {
     if style.get_effects().clip.0.is_some() {
         let mut style = Arc::make_mut(style);
         let effects_style = Arc::make_mut(&mut style.effects);
         effects_style.clip.0 = None
     }
 }
 
 pub fn is_supported_property(property: &str) -> bool {
--- a/servo/components/style/restyle_hints.rs
+++ b/servo/components/style/restyle_hints.rs
@@ -1,20 +1,21 @@
 /* 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/. */
 
 //! Restyle hints: an optimization to avoid unnecessarily matching selectors.
 
 use attr::{AttrIdentifier, AttrValue};
 use element_state::*;
-use selector_impl::SelectorImplExt;
+use selector_impl::{SelectorImplExt, TheSelectorImpl, AttrString};
 use selectors::matching::matches_compound_selector;
 use selectors::parser::{AttrSelector, Combinator, CompoundSelector, SelectorImpl, SimpleSelector};
 use selectors::{Element, MatchAttrGeneric};
+#[cfg(feature = "gecko")] use selectors::MatchAttr;
 use std::clone::Clone;
 use std::sync::Arc;
 use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
 
 /// When the ElementState of an element (like IN_HOVER_STATE) changes, certain
 /// pseudo-classes (like :hover) may require us to restyle that element, its
 /// siblings, and/or its descendants. Similarly, when various attributes of an
 /// element change, we may also need to restyle things with id, class, and attribute
@@ -83,37 +84,37 @@ static EMPTY_SNAPSHOT: ElementSnapshot =
 
 // FIXME(bholley): This implementation isn't going to work for geckolib, because
 // it's fundamentally based on get_attr/match_attr, which we don't want to support
 // that configuration due to the overhead of converting between UTF-16 and UTF-8.
 // We'll need to figure something out when we start using restyle hints with
 // geckolib, but in the mean time we can just use the trait parameters to
 // specialize it to the Servo configuration.
 struct ElementWrapper<'a, E>
-    where E: Element<AttrString=String>,
+    where E: Element<AttrString=AttrString>,
           E::Impl: SelectorImplExt {
     element: E,
     snapshot: &'a ElementSnapshot,
 }
 
 impl<'a, E> ElementWrapper<'a, E>
-    where E: Element<AttrString=String>,
+    where E: Element<AttrString=AttrString>,
           E::Impl: SelectorImplExt {
     pub fn new(el: E) -> ElementWrapper<'a, E> {
         ElementWrapper { element: el, snapshot: &EMPTY_SNAPSHOT }
     }
 
     pub fn new_with_snapshot(el: E, snapshot: &'a ElementSnapshot) -> ElementWrapper<'a, E> {
         ElementWrapper { element: el, snapshot: snapshot }
     }
 }
 
 #[cfg(not(feature = "gecko"))]
 impl<'a, E> MatchAttrGeneric for ElementWrapper<'a, E>
-    where E: Element<AttrString=String>,
+    where E: Element<AttrString=AttrString>,
           E: MatchAttrGeneric,
           E::Impl: SelectorImplExt {
     fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
                     where F: Fn(&str) -> bool {
         use selectors::parser::NamespaceConstraint;
         match self.snapshot.attrs {
             Some(_) => {
                 let html = self.is_html_element_in_html_document();
@@ -124,28 +125,56 @@ impl<'a, E> MatchAttrGeneric for Element
                 }.map_or(false, |v| test(v))
             },
             None => self.element.match_attr(attr, test)
         }
     }
 }
 
 #[cfg(feature = "gecko")]
-impl<'a, E> MatchAttrGeneric for ElementWrapper<'a, E>
-    where E: Element<AttrString=String>,
-          E: MatchAttrGeneric,
+impl<'a, E> MatchAttr for ElementWrapper<'a, E>
+    where E: Element<AttrString=AttrString>,
           E::Impl: SelectorImplExt {
-    fn match_attr<F>(&self, _: &AttrSelector, _: F) -> bool
-                    where F: Fn(&str) -> bool {
+    type AttrString = AttrString;
+
+    fn match_attr_has(&self, _attr: &AttrSelector) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_equals(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_equals_ignore_ascii_case(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_includes(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_dash(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_prefix(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_substring(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
+        panic!("Not implemented for Gecko - this system will need to be redesigned");
+    }
+
+    fn match_attr_suffix(&self, _attr: &AttrSelector, _value: &Self::AttrString) -> bool {
         panic!("Not implemented for Gecko - this system will need to be redesigned");
     }
 }
 
 impl<'a, E> Element for ElementWrapper<'a, E>
-    where E: Element<AttrString=String>,
+    where E: Element<AttrString=AttrString>,
           E: MatchAttrGeneric,
           E::Impl: SelectorImplExt {
     type Impl = E::Impl;
 
     fn match_non_ts_pseudo_class(&self,
                                  pseudo_class: <Self::Impl as SelectorImpl>::NonTSPseudoClass) -> bool {
         let flag = Self::Impl::pseudo_class_state_flag(&pseudo_class);
         if flag == ElementState::empty() {
@@ -208,24 +237,24 @@ impl<'a, E> Element for ElementWrapper<'
                     for c in v.as_tokens() { callback(c) }
                 }
             }
             None => self.element.each_class(callback),
         }
     }
 }
 
-fn selector_to_state<Impl: SelectorImplExt>(sel: &SimpleSelector<Impl>) -> ElementState {
+fn selector_to_state(sel: &SimpleSelector<TheSelectorImpl>) -> ElementState {
     match *sel {
-        SimpleSelector::NonTSPseudoClass(ref pc) => Impl::pseudo_class_state_flag(pc),
+        SimpleSelector::NonTSPseudoClass(ref pc) => TheSelectorImpl::pseudo_class_state_flag(pc),
         _ => ElementState::empty(),
     }
 }
 
-fn is_attr_selector<Impl: SelectorImpl>(sel: &SimpleSelector<Impl>) -> bool {
+fn is_attr_selector(sel: &SimpleSelector<TheSelectorImpl>) -> bool {
     match *sel {
         SimpleSelector::ID(_) |
         SimpleSelector::Class(_) |
         SimpleSelector::AttrExists(_) |
         SimpleSelector::AttrEqual(_, _, _) |
         SimpleSelector::AttrIncludes(_, _) |
         SimpleSelector::AttrDashMatch(_, _) |
         SimpleSelector::AttrPrefixMatch(_, _) |
@@ -282,34 +311,34 @@ impl Sensitivities {
 //
 // We generate a Dependency for both |a _ b:X _| and |a _ b:X _ c _ d:Y _|, even
 // though those selectors may not appear on their own in any stylesheet. This allows
 // us to quickly scan through the dependency sites of all style rules and determine the
 // maximum effect that a given state or attribute change may have on the style of
 // elements in the document.
 #[derive(Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-struct Dependency<Impl: SelectorImplExt> {
-    selector: Arc<CompoundSelector<Impl>>,
+struct Dependency {
+    selector: Arc<CompoundSelector<TheSelectorImpl>>,
     combinator: Option<Combinator>,
     sensitivities: Sensitivities,
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct DependencySet<Impl: SelectorImplExt> {
-    deps: Vec<Dependency<Impl>>,
+pub struct DependencySet {
+    deps: Vec<Dependency>,
 }
 
-impl<Impl: SelectorImplExt> DependencySet<Impl> {
-    pub fn new() -> DependencySet<Impl> {
+impl DependencySet {
+    pub fn new() -> Self {
         DependencySet { deps: Vec::new() }
     }
 
-    pub fn note_selector(&mut self, selector: Arc<CompoundSelector<Impl>>) {
+    pub fn note_selector(&mut self, selector: Arc<CompoundSelector<TheSelectorImpl>>) {
         let mut cur = selector;
         let mut combinator: Option<Combinator> = None;
         loop {
             let mut sensitivities = Sensitivities::new();
             for s in &cur.simple_selectors {
                 sensitivities.states.insert(selector_to_state(s));
                 if !sensitivities.attrs {
                     sensitivities.attrs = is_attr_selector(s);
@@ -333,20 +362,20 @@ impl<Impl: SelectorImplExt> DependencySe
         }
     }
 
     pub fn clear(&mut self) {
         self.deps.clear();
     }
 }
 
-impl<Impl: SelectorImplExt<AttrString=String>> DependencySet<Impl> {
+impl DependencySet {
     pub fn compute_hint<E>(&self, el: &E, snapshot: &ElementSnapshot, current_state: ElementState)
                           -> RestyleHint
-                          where E: Element<Impl=Impl, AttrString=Impl::AttrString> + Clone + MatchAttrGeneric {
+                          where E: Element<Impl=TheSelectorImpl, AttrString=AttrString> + Clone + MatchAttrGeneric {
         let state_changes = snapshot.state.map_or(ElementState::empty(), |old_state| current_state ^ old_state);
         let attrs_changed = snapshot.attrs.is_some();
         let mut hint = RestyleHint::empty();
         for dep in &self.deps {
             if state_changes.intersects(dep.sensitivities.states) || (attrs_changed && dep.sensitivities.attrs) {
                 let old_el: ElementWrapper<E> = ElementWrapper::new_with_snapshot(el.clone(), snapshot);
                 let matched_then = matches_compound_selector(&*dep.selector, &old_el, None, &mut false);
                 let matches_now = matches_compound_selector(&*dep.selector, el, None, &mut false);
--- a/servo/components/style/selector_impl.rs
+++ b/servo/components/style/selector_impl.rs
@@ -1,22 +1,31 @@
 /* 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/. */
 
 //! The pseudo-classes and pseudo-elements supported by the style system.
 
 use element_state::ElementState;
-use properties::{self, ServoComputedValues};
-use selector_matching::{USER_OR_USER_AGENT_STYLESHEETS, QUIRKS_MODE_STYLESHEET};
 use selectors::Element;
-use selectors::parser::{ParserContext, SelectorImpl};
+use selectors::parser::SelectorImpl;
 use std::fmt::Debug;
 use stylesheets::Stylesheet;
 
+pub type AttrString = <TheSelectorImpl as SelectorImpl>::AttrString;
+
+#[cfg(feature = "servo")]
+pub use servo_selector_impl::ServoSelectorImpl;
+
+#[cfg(feature = "servo")]
+pub use servo_selector_impl::{ServoSelectorImpl as TheSelectorImpl, PseudoElement, NonTSPseudoClass};
+
+#[cfg(feature = "gecko")]
+pub use gecko_selector_impl::{GeckoSelectorImpl as TheSelectorImpl, PseudoElement, NonTSPseudoClass};
+
 /// This function determines if a pseudo-element is eagerly cascaded or not.
 ///
 /// Eagerly cascaded pseudo-elements are "normal" pseudo-elements (i.e.
 /// `::before` and `::after`). They inherit styles normally as another
 /// selector would do, and they're part of the cascade.
 ///
 /// Lazy pseudo-elements are affected by selector matching, but they're only
 /// computed when needed, and not before. They're useful for general
@@ -54,25 +63,23 @@ impl PseudoElementCascadeType {
     }
 
     #[inline]
     pub fn is_precomputed(&self) -> bool {
         *self == PseudoElementCascadeType::Precomputed
     }
 }
 
-pub trait ElementExt: Element {
+pub trait ElementExt: Element<Impl=TheSelectorImpl, AttrString=<TheSelectorImpl as SelectorImpl>::AttrString> {
     fn is_link(&self) -> bool;
 }
 
 // NB: The `Clone` trait is here for convenience due to:
 // https://github.com/rust-lang/rust/issues/26925
 pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized + 'static {
-    type ComputedValues: properties::ComputedValues;
-
     fn pseudo_element_cascade_type(pseudo: &Self::PseudoElement) -> PseudoElementCascadeType;
 
     fn each_pseudo_element<F>(mut fun: F)
         where F: FnMut(Self::PseudoElement);
 
     #[inline]
     fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
         where F: FnMut(<Self as SelectorImpl>::PseudoElement) {
@@ -92,195 +99,12 @@ pub trait SelectorImplExt : SelectorImpl
             }
         })
     }
 
     fn pseudo_is_before_or_after(pseudo: &Self::PseudoElement) -> bool;
 
     fn pseudo_class_state_flag(pc: &Self::NonTSPseudoClass) -> ElementState;
 
-    fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>];
-
-    fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>>;
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum PseudoElement {
-    Before,
-    After,
-    Selection,
-    DetailsSummary,
-    DetailsContent,
-}
-
-impl PseudoElement {
-    #[inline]
-    pub fn is_before_or_after(&self) -> bool {
-        match *self {
-            PseudoElement::Before |
-            PseudoElement::After => true,
-            _ => false,
-        }
-    }
-
-    #[inline]
-    pub fn cascade_type(&self) -> PseudoElementCascadeType {
-        match *self {
-            PseudoElement::Before |
-            PseudoElement::After |
-            PseudoElement::Selection => PseudoElementCascadeType::Eager,
-            PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
-            PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
-        }
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum NonTSPseudoClass {
-    AnyLink,
-    Link,
-    Visited,
-    Active,
-    Focus,
-    Hover,
-    Enabled,
-    Disabled,
-    Checked,
-    Indeterminate,
-    ServoNonZeroBorder,
-    ReadWrite,
-    ReadOnly,
-    PlaceholderShown,
-}
-
-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,
-            Enabled => IN_ENABLED_STATE,
-            Disabled => IN_DISABLED_STATE,
-            Checked => IN_CHECKED_STATE,
-            Indeterminate => IN_INDETERMINATE_STATE,
-            ReadOnly | ReadWrite => IN_READ_WRITE_STATE,
-            PlaceholderShown => IN_PLACEHOLDER_SHOWN_STATE,
-
-            AnyLink |
-            Link |
-            Visited |
-            ServoNonZeroBorder => ElementState::empty(),
-        }
-    }
-}
-
-#[derive(Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct ServoSelectorImpl;
-
-impl SelectorImpl for ServoSelectorImpl {
-    type AttrString = String;
-    type PseudoElement = PseudoElement;
-    type NonTSPseudoClass = NonTSPseudoClass;
+    fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet];
 
-    fn parse_non_ts_pseudo_class(context: &ParserContext,
-                                 name: &str) -> Result<NonTSPseudoClass, ()> {
-        use self::NonTSPseudoClass::*;
-        let pseudo_class = match_ignore_ascii_case! { name,
-            "any-link" => AnyLink,
-            "link" => Link,
-            "visited" => Visited,
-            "active" => Active,
-            "focus" => Focus,
-            "hover" => Hover,
-            "enabled" => Enabled,
-            "disabled" => Disabled,
-            "checked" => Checked,
-            "indeterminate" => Indeterminate,
-            "read-write" => ReadWrite,
-            "read-only" => ReadOnly,
-            "placeholder-shown" => PlaceholderShown,
-            "-servo-nonzero-border" => {
-                if !context.in_user_agent_stylesheet {
-                    return Err(());
-                }
-                ServoNonZeroBorder
-            },
-            _ => return Err(())
-        };
-
-        Ok(pseudo_class)
-    }
-
-    fn parse_pseudo_element(context: &ParserContext,
-                            name: &str) -> Result<PseudoElement, ()> {
-        use self::PseudoElement::*;
-        let pseudo_element = match_ignore_ascii_case! { name,
-            "before" => Before,
-            "after" => After,
-            "selection" => Selection,
-            "-servo-details-summary" => {
-                if !context.in_user_agent_stylesheet {
-                    return Err(())
-                }
-                DetailsSummary
-            },
-            "-servo-details-content" => {
-                if !context.in_user_agent_stylesheet {
-                    return Err(())
-                }
-                DetailsContent
-            },
-            _ => return Err(())
-        };
-
-        Ok(pseudo_element)
-    }
+    fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet>;
 }
-
-impl SelectorImplExt for ServoSelectorImpl {
-    type ComputedValues = ServoComputedValues;
-
-    #[inline]
-    fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
-        pseudo.cascade_type()
-    }
-
-    #[inline]
-    fn each_pseudo_element<F>(mut fun: F)
-        where F: FnMut(PseudoElement) {
-        fun(PseudoElement::Before);
-        fun(PseudoElement::After);
-        fun(PseudoElement::DetailsContent);
-        fun(PseudoElement::DetailsSummary);
-        fun(PseudoElement::Selection);
-    }
-
-    #[inline]
-    fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
-        pc.state_flag()
-    }
-
-    #[inline]
-    fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
-        pseudo.is_before_or_after()
-    }
-
-    #[inline]
-    fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>] {
-        &*USER_OR_USER_AGENT_STYLESHEETS
-    }
-
-    #[inline]
-    fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>> {
-        Some(&*QUIRKS_MODE_STYLESHEET)
-    }
-}
-
-impl<E: Element<Impl=ServoSelectorImpl, AttrString=String>> ElementExt for E {
-    fn is_link(&self) -> bool {
-        self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
-    }
-}
--- a/servo/components/style/selector_matching.rs
+++ b/servo/components/style/selector_matching.rs
@@ -4,96 +4,36 @@
 
 //! Selector matching.
 
 use dom::PresentationalHintsSynthetizer;
 use element_state::*;
 use error_reporting::StdoutErrorReporter;
 use keyframes::KeyframesAnimation;
 use media_queries::{Device, MediaType};
-use parser::ParserContextExtraData;
-use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
+use properties::{self, PropertyDeclaration, PropertyDeclarationBlock, ComputedValues};
 use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
-use selector_impl::{SelectorImplExt, ServoSelectorImpl};
+use selector_impl::{SelectorImplExt, TheSelectorImpl, PseudoElement, AttrString};
 use selectors::bloom::BloomFilter;
 use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
 use selectors::matching::{Rule, SelectorMap};
-use selectors::parser::SelectorImpl;
 use selectors::{Element, MatchAttrGeneric};
 use sink::Push;
 use smallvec::VecLike;
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
-use std::process;
 use std::sync::Arc;
 use string_cache::Atom;
 use style_traits::viewport::ViewportConstraints;
 use stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet};
-use url::Url;
-use util::opts;
-use util::resource_files::read_resource_file;
 use viewport::{MaybeNew, ViewportRuleCascade};
 
 
 pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>;
 
-lazy_static! {
-    pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet<ServoSelectorImpl>> = {
-        let mut stylesheets = vec!();
-        // FIXME: presentational-hints.css should be at author origin with zero specificity.
-        //        (Does it make a difference?)
-        for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] {
-            match read_resource_file(filename) {
-                Ok(res) => {
-                    let ua_stylesheet = Stylesheet::from_bytes(
-                        &res,
-                        Url::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
-                        None,
-                        None,
-                        Origin::UserAgent,
-                        Box::new(StdoutErrorReporter),
-                        ParserContextExtraData::default());
-                    stylesheets.push(ua_stylesheet);
-                }
-                Err(..) => {
-                    error!("Failed to load UA stylesheet {}!", filename);
-                    process::exit(1);
-                }
-            }
-        }
-        for &(ref contents, ref url) in &opts::get().user_stylesheets {
-            stylesheets.push(Stylesheet::from_bytes(
-                &contents, url.clone(), None, None, Origin::User, Box::new(StdoutErrorReporter),
-                ParserContextExtraData::default()));
-        }
-        stylesheets
-    };
-}
-
-lazy_static! {
-    pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet<ServoSelectorImpl> = {
-        match read_resource_file("quirks-mode.css") {
-            Ok(res) => {
-                Stylesheet::from_bytes(
-                    &res,
-                    Url::parse("chrome://resources/quirks-mode.css").unwrap(),
-                    None,
-                    None,
-                    Origin::UserAgent,
-                    Box::new(StdoutErrorReporter),
-                    ParserContextExtraData::default())
-            },
-            Err(..) => {
-                error!("Stylist failed to load 'quirks-mode.css'!");
-                process::exit(1);
-            }
-        }
-    };
-}
-
 /// This structure holds all the selectors and device characteristics
 /// for a given document. The selectors are converted into `Rule`s
 /// (defined in rust-selectors), and introduced in a `SelectorMap`
 /// depending on the pseudo-element (see `PerPseudoElementSelectorMap`),
 /// stylesheet origin (see `PerOriginSelectorMap`), and priority
 /// (see the `normal` and `important` fields in `PerOriginSelectorMap`).
 ///
 /// This structure is effectively created once per pipeline, in the
@@ -101,118 +41,116 @@ lazy_static! {
 ///
 /// The stylist is parameterized on `SelectorImplExt`, a trait that extends
 /// `selectors::parser::SelectorImpl`, and that allows to customise what
 /// pseudo-classes and pseudo-elements are parsed. This is actually either
 /// `ServoSelectorImpl`, the implementation used by Servo's layout system in
 /// regular builds, or `GeckoSelectorImpl`, the implementation used in the
 /// geckolib port.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct Stylist<Impl: SelectorImplExt> {
+pub struct Stylist {
     /// Device that the stylist is currently evaluating against.
     pub device: Device,
 
     /// Viewport constraints based on the current device.
     viewport_constraints: Option<ViewportConstraints>,
 
     /// If true, the quirks-mode stylesheet is applied.
     quirks_mode: bool,
 
     /// If true, the device has changed, and the stylist needs to be updated.
     is_device_dirty: bool,
 
     /// The current selector maps, after evaluating media
     /// rules against the current device.
-    element_map: PerPseudoElementSelectorMap<Impl>,
+    element_map: PerPseudoElementSelectorMap,
 
     /// The selector maps corresponding to a given pseudo-element
     /// (depending on the implementation)
-    pseudos_map: HashMap<Impl::PseudoElement,
-                         PerPseudoElementSelectorMap<Impl>,
+    pseudos_map: HashMap<PseudoElement,
+                         PerPseudoElementSelectorMap,
                          BuildHasherDefault<::fnv::FnvHasher>>,
 
     /// A map with all the animations indexed by name.
     animations: HashMap<Atom, KeyframesAnimation>,
 
     /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
     /// These are eagerly computed once, and then used to resolve the new
     /// computed values on the fly on layout.
-    precomputed_pseudo_element_decls: HashMap<Impl::PseudoElement,
+    precomputed_pseudo_element_decls: HashMap<PseudoElement,
                                               Vec<DeclarationBlock>,
                                               BuildHasherDefault<::fnv::FnvHasher>>,
 
     rules_source_order: usize,
 
     /// Selector dependencies used to compute restyle hints.
-    state_deps: DependencySet<Impl>,
+    state_deps: DependencySet,
 }
 
-impl<Impl: SelectorImplExt> Stylist<Impl> {
+impl Stylist {
     #[inline]
-    pub fn new(device: Device) -> Stylist<Impl> {
+    pub fn new(device: Device) -> Self {
         let mut stylist = Stylist {
             viewport_constraints: None,
             device: device,
             is_device_dirty: true,
             quirks_mode: false,
 
             element_map: PerPseudoElementSelectorMap::new(),
             pseudos_map: HashMap::with_hasher(Default::default()),
             animations: HashMap::with_hasher(Default::default()),
             precomputed_pseudo_element_decls: HashMap::with_hasher(Default::default()),
             rules_source_order: 0,
             state_deps: DependencySet::new(),
         };
 
-        Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
+        TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
             stylist.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
         });
 
         // FIXME: Add iso-8859-9.css when the document’s encoding is ISO-8859-8.
 
         stylist
     }
 
-    pub fn update(&mut self, doc_stylesheets: &[Arc<Stylesheet<Impl>>],
-                  stylesheets_changed: bool) -> bool
-                  where Impl: 'static {
+    pub fn update(&mut self, doc_stylesheets: &[Arc<Stylesheet>], stylesheets_changed: bool) -> bool {
         if !(self.is_device_dirty || stylesheets_changed) {
             return false;
         }
 
         self.element_map = PerPseudoElementSelectorMap::new();
         self.pseudos_map = HashMap::with_hasher(Default::default());
         self.animations = HashMap::with_hasher(Default::default());
-        Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
+        TheSelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
             self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
         });
 
         self.precomputed_pseudo_element_decls = HashMap::with_hasher(Default::default());
         self.rules_source_order = 0;
         self.state_deps.clear();
 
-        for ref stylesheet in Impl::get_user_or_user_agent_stylesheets().iter() {
+        for ref stylesheet in TheSelectorImpl::get_user_or_user_agent_stylesheets().iter() {
             self.add_stylesheet(&stylesheet);
         }
 
         if self.quirks_mode {
-            if let Some(s) = Impl::get_quirks_mode_stylesheet() {
+            if let Some(s) = TheSelectorImpl::get_quirks_mode_stylesheet() {
                 self.add_stylesheet(s);
             }
         }
 
         for ref stylesheet in doc_stylesheets.iter() {
             self.add_stylesheet(stylesheet);
         }
 
         self.is_device_dirty = false;
         true
     }
 
-    fn add_stylesheet(&mut self, stylesheet: &Stylesheet<Impl>) {
+    fn add_stylesheet(&mut self, stylesheet: &Stylesheet) {
         if !stylesheet.is_effective_for_device(&self.device) {
             return;
         }
         let mut rules_source_order = self.rules_source_order;
 
         // Take apart the StyleRule into individual Rules and insert
         // them into the SelectorMap of that priority.
         macro_rules! append(
@@ -266,17 +204,17 @@ impl<Impl: SelectorImplExt> Stylist<Impl
                         self.animations.remove(&keyframes_rule.name);
                     }
                 }
                 // We don't care about any other rule.
                 _ => {}
             }
         }
 
-        Impl::each_precomputed_pseudo_element(|pseudo| {
+        TheSelectorImpl::each_precomputed_pseudo_element(|pseudo| {
             // TODO: Consider not doing this and just getting the rules on the
             // fly. It should be a bit slower, but we'd take rid of the
             // extra field, and avoid this precomputation entirely.
             if let Some(map) = self.pseudos_map.remove(&pseudo) {
                 let mut declarations = vec![];
 
                 map.user_agent.normal.get_universal_rules(&mut declarations);
                 map.user_agent.important.get_universal_rules(&mut declarations);
@@ -284,41 +222,41 @@ impl<Impl: SelectorImplExt> Stylist<Impl
                 self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
             }
         })
     }
 
     /// Computes the style for a given "precomputed" pseudo-element, taking the
     /// universal rules and applying them.
     pub fn precomputed_values_for_pseudo(&self,
-                                         pseudo: &Impl::PseudoElement,
-                                         parent: Option<&Arc<Impl::ComputedValues>>)
-                                         -> Option<Arc<Impl::ComputedValues>> {
-        debug_assert!(Impl::pseudo_element_cascade_type(pseudo).is_precomputed());
+                                         pseudo: &PseudoElement,
+                                         parent: Option<&Arc<ComputedValues>>)
+                                         -> Option<Arc<ComputedValues>> {
+        debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_precomputed());
         if let Some(declarations) = self.precomputed_pseudo_element_decls.get(pseudo) {
             let (computed, _) =
                 properties::cascade(self.device.au_viewport_size(),
                                     &declarations, false,
                                     parent.map(|p| &**p),
                                     None,
                                     Box::new(StdoutErrorReporter));
             Some(Arc::new(computed))
         } else {
             parent.map(|p| p.clone())
         }
     }
 
     pub fn lazily_compute_pseudo_element_style<E>(&self,
                                                   element: &E,
-                                                  pseudo: &Impl::PseudoElement,
-                                                  parent: &Arc<Impl::ComputedValues>)
-                                                  -> Option<Arc<Impl::ComputedValues>>
-                                                  where E: Element<Impl=Impl, AttrString=Impl::AttrString> +
+                                                  pseudo: &PseudoElement,
+                                                  parent: &Arc<ComputedValues>)
+                                                  -> Option<Arc<ComputedValues>>
+                                                  where E: Element<Impl=TheSelectorImpl, AttrString=AttrString> +
                                                         PresentationalHintsSynthetizer {
-        debug_assert!(Impl::pseudo_element_cascade_type(pseudo).is_lazy());
+        debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_lazy());
         if self.pseudos_map.get(pseudo).is_none() {
             return None;
         }
 
         let mut declarations = vec![];
 
         // NB: This being cached could be worth it, maybe allow an optional
         // ApplicableDeclarationsCache?.
@@ -331,17 +269,17 @@ impl<Impl: SelectorImplExt> Stylist<Impl
         let (computed, _) =
             properties::cascade(self.device.au_viewport_size(),
                                 &declarations, false,
                                 Some(&**parent), None,
                                 Box::new(StdoutErrorReporter));
         Some(Arc::new(computed))
     }
 
-    pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet<Impl>>]) {
+    pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
         let cascaded_rule = stylesheets.iter()
             .flat_map(|s| s.effective_rules(&self.device).viewport())
             .cascade();
 
         self.viewport_constraints = ViewportConstraints::maybe_new(device.viewport_size, &cascaded_rule);
         if let Some(ref constraints) = self.viewport_constraints {
             device = Device::new(MediaType::Screen, constraints.size);
         }
@@ -369,27 +307,28 @@ impl<Impl: SelectorImplExt> Stylist<Impl
     /// that is, whether the matched selectors are simple enough to allow the
     /// 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<&PropertyDeclarationBlock>,
-                                        pseudo_element: Option<&Impl::PseudoElement>,
+                                        pseudo_element: Option<&PseudoElement>,
                                         applicable_declarations: &mut V)
                                         -> bool
-                                        where E: Element<Impl=Impl, AttrString=Impl::AttrString> +
+                                        where E: Element<Impl=TheSelectorImpl, AttrString=AttrString> +
                                                  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");
         debug_assert!(pseudo_element.is_none() ||
-                      !Impl::pseudo_element_cascade_type(pseudo_element.as_ref().unwrap()).is_precomputed());
+                      !TheSelectorImpl::pseudo_element_cascade_type(pseudo_element.as_ref().unwrap())
+                        .is_precomputed());
 
         let map = match pseudo_element {
             Some(ref pseudo) => self.pseudos_map.get(pseudo).unwrap(),
             None => &self.element_map,
         };
 
         let mut shareable = true;
 
@@ -456,77 +395,76 @@ impl<Impl: SelectorImplExt> Stylist<Impl
     pub fn is_device_dirty(&self) -> bool {
         self.is_device_dirty
     }
 
     #[inline]
     pub fn animations(&self) -> &HashMap<Atom, KeyframesAnimation> {
         &self.animations
     }
-}
 
-impl<Impl: SelectorImplExt<AttrString=String>> Stylist<Impl> {
     pub fn compute_restyle_hint<E>(&self, element: &E,
                                    snapshot: &ElementSnapshot,
                                    // NB: We need to pass current_state as an argument because
                                    // selectors::Element doesn't provide access to ElementState
                                    // directly, and computing it from the ElementState would be
                                    // more expensive than getting it directly from the caller.
                                    current_state: ElementState)
                                    -> RestyleHint
-                                   where E: Element<Impl=Impl, AttrString=String> + Clone + MatchAttrGeneric {
+                                   where E: Element<Impl=TheSelectorImpl, AttrString=AttrString>
+                                        + Clone + MatchAttrGeneric {
         self.state_deps.compute_hint(element, snapshot, current_state)
     }
 }
 
 
 /// Map that contains the CSS rules for a given origin.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-struct PerOriginSelectorMap<Impl: SelectorImpl> {
+struct PerOriginSelectorMap {
     /// Rules that contains at least one property declararion with
     /// normal importance.
-    normal: SelectorMap<Vec<PropertyDeclaration>, Impl>,
+    normal: SelectorMap<Vec<PropertyDeclaration>, TheSelectorImpl>,
     /// Rules that contains at least one property declararion with
     /// !important.
-    important: SelectorMap<Vec<PropertyDeclaration>, Impl>,
+    important: SelectorMap<Vec<PropertyDeclaration>, TheSelectorImpl>,
 }
 
-impl<Impl: SelectorImpl> PerOriginSelectorMap<Impl> {
+impl PerOriginSelectorMap {
     #[inline]
-    fn new() -> PerOriginSelectorMap<Impl> {
+    fn new() -> Self {
         PerOriginSelectorMap {
             normal: SelectorMap::new(),
             important: SelectorMap::new(),
         }
     }
 }
 
 /// Map that contains the CSS rules for a specific PseudoElement
 /// (or lack of PseudoElement).
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-struct PerPseudoElementSelectorMap<Impl: SelectorImpl> {
+struct PerPseudoElementSelectorMap {
     /// Rules from user agent stylesheets
-    user_agent: PerOriginSelectorMap<Impl>,
+    user_agent: PerOriginSelectorMap,
     /// Rules from author stylesheets
-    author: PerOriginSelectorMap<Impl>,
+    author: PerOriginSelectorMap,
     /// Rules from user stylesheets
-    user: PerOriginSelectorMap<Impl>,
+    user: PerOriginSelectorMap,
 }
 
-impl<Impl: SelectorImpl> PerPseudoElementSelectorMap<Impl> {
+impl PerPseudoElementSelectorMap {
     #[inline]
-    fn new() -> PerPseudoElementSelectorMap<Impl> {
+    fn new() -> Self {
         PerPseudoElementSelectorMap {
             user_agent: PerOriginSelectorMap::new(),
             author: PerOriginSelectorMap::new(),
             user: PerOriginSelectorMap::new(),
         }
     }
 
     #[inline]
-    fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap<Impl> {
+    fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap {
         match *origin {
             Origin::UserAgent => &mut self.user_agent,
             Origin::Author => &mut self.author,
             Origin::User => &mut self.user,
         }
     }
 }
deleted file mode 100644
--- a/servo/components/style/servo.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-/* 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/. */
-//! Concrete types for servo Style implementation
-
-use animation;
-use context;
-use data;
-use properties::ServoComputedValues;
-use selector_impl::ServoSelectorImpl;
-use selector_matching;
-use stylesheets;
-
-pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>;
-pub type PrivateStyleData = data::PrivateStyleData<ServoSelectorImpl, ServoComputedValues>;
-pub type Stylist = selector_matching::Stylist<ServoSelectorImpl>;
-pub type SharedStyleContext = context::SharedStyleContext<ServoSelectorImpl>;
-pub type LocalStyleContextCreationInfo = context::LocalStyleContextCreationInfo<ServoSelectorImpl>;
-pub type Animation = animation::Animation<ServoSelectorImpl>;
new file mode 100644
--- /dev/null
+++ b/servo/components/style/servo_selector_impl.rs
@@ -0,0 +1,250 @@
+/* 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 element_state::ElementState;
+use error_reporting::StdoutErrorReporter;
+use parser::ParserContextExtraData;
+use selector_impl::{SelectorImplExt, ElementExt, PseudoElementCascadeType, TheSelectorImpl};
+use selectors::Element;
+use selectors::parser::{ParserContext, SelectorImpl};
+use std::process;
+use stylesheets::{Stylesheet, Origin};
+use url::Url;
+use util::opts;
+use util::resource_files::read_resource_file;
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum PseudoElement {
+    Before,
+    After,
+    Selection,
+    DetailsSummary,
+    DetailsContent,
+}
+
+impl PseudoElement {
+    #[inline]
+    pub fn is_before_or_after(&self) -> bool {
+        match *self {
+            PseudoElement::Before |
+            PseudoElement::After => true,
+            _ => false,
+        }
+    }
+
+    #[inline]
+    pub fn cascade_type(&self) -> PseudoElementCascadeType {
+        match *self {
+            PseudoElement::Before |
+            PseudoElement::After |
+            PseudoElement::Selection => PseudoElementCascadeType::Eager,
+            PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
+            PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum NonTSPseudoClass {
+    AnyLink,
+    Link,
+    Visited,
+    Active,
+    Focus,
+    Hover,
+    Enabled,
+    Disabled,
+    Checked,
+    Indeterminate,
+    ServoNonZeroBorder,
+    ReadWrite,
+    ReadOnly,
+    PlaceholderShown,
+}
+
+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,
+            Enabled => IN_ENABLED_STATE,
+            Disabled => IN_DISABLED_STATE,
+            Checked => IN_CHECKED_STATE,
+            Indeterminate => IN_INDETERMINATE_STATE,
+            ReadOnly | ReadWrite => IN_READ_WRITE_STATE,
+            PlaceholderShown => IN_PLACEHOLDER_SHOWN_STATE,
+
+            AnyLink |
+            Link |
+            Visited |
+            ServoNonZeroBorder => ElementState::empty(),
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct ServoSelectorImpl;
+
+impl SelectorImpl for ServoSelectorImpl {
+    type AttrString = String;
+    type PseudoElement = PseudoElement;
+    type NonTSPseudoClass = NonTSPseudoClass;
+
+    fn parse_non_ts_pseudo_class(context: &ParserContext,
+                                 name: &str) -> Result<NonTSPseudoClass, ()> {
+        use self::NonTSPseudoClass::*;
+        let pseudo_class = match_ignore_ascii_case! { name,
+            "any-link" => AnyLink,
+            "link" => Link,
+            "visited" => Visited,
+            "active" => Active,
+            "focus" => Focus,
+            "hover" => Hover,
+            "enabled" => Enabled,
+            "disabled" => Disabled,
+            "checked" => Checked,
+            "indeterminate" => Indeterminate,
+            "read-write" => ReadWrite,
+            "read-only" => ReadOnly,
+            "placeholder-shown" => PlaceholderShown,
+            "-servo-nonzero-border" => {
+                if !context.in_user_agent_stylesheet {
+                    return Err(());
+                }
+                ServoNonZeroBorder
+            },
+            _ => return Err(())
+        };
+
+        Ok(pseudo_class)
+    }
+
+    fn parse_pseudo_element(context: &ParserContext,
+                            name: &str) -> Result<PseudoElement, ()> {
+        use self::PseudoElement::*;
+        let pseudo_element = match_ignore_ascii_case! { name,
+            "before" => Before,
+            "after" => After,
+            "selection" => Selection,
+            "-servo-details-summary" => {
+                if !context.in_user_agent_stylesheet {
+                    return Err(())
+                }
+                DetailsSummary
+            },
+            "-servo-details-content" => {
+                if !context.in_user_agent_stylesheet {
+                    return Err(())
+                }
+                DetailsContent
+            },
+            _ => return Err(())
+        };
+
+        Ok(pseudo_element)
+    }
+}
+
+impl SelectorImplExt for ServoSelectorImpl {
+    #[inline]
+    fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
+        pseudo.cascade_type()
+    }
+
+    #[inline]
+    fn each_pseudo_element<F>(mut fun: F)
+        where F: FnMut(PseudoElement) {
+        fun(PseudoElement::Before);
+        fun(PseudoElement::After);
+        fun(PseudoElement::DetailsContent);
+        fun(PseudoElement::DetailsSummary);
+        fun(PseudoElement::Selection);
+    }
+
+    #[inline]
+    fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
+        pc.state_flag()
+    }
+
+    #[inline]
+    fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
+        pseudo.is_before_or_after()
+    }
+
+    #[inline]
+    fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet] {
+        &*USER_OR_USER_AGENT_STYLESHEETS
+    }
+
+    #[inline]
+    fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet> {
+        Some(&*QUIRKS_MODE_STYLESHEET)
+    }
+}
+
+impl<E: Element<Impl=TheSelectorImpl, AttrString=String>> ElementExt for E {
+    fn is_link(&self) -> bool {
+        self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
+    }
+}
+
+lazy_static! {
+    pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet> = {
+        let mut stylesheets = vec!();
+        // FIXME: presentational-hints.css should be at author origin with zero specificity.
+        //        (Does it make a difference?)
+        for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] {
+            match read_resource_file(filename) {
+                Ok(res) => {
+                    let ua_stylesheet = Stylesheet::from_bytes(
+                        &res,
+                        Url::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
+                        None,
+                        None,
+                        Origin::UserAgent,
+                        Box::new(StdoutErrorReporter),
+                        ParserContextExtraData::default());
+                    stylesheets.push(ua_stylesheet);
+                }
+                Err(..) => {
+                    error!("Failed to load UA stylesheet {}!", filename);
+                    process::exit(1);
+                }
+            }
+        }
+        for &(ref contents, ref url) in &opts::get().user_stylesheets {
+            stylesheets.push(Stylesheet::from_bytes(
+                &contents, url.clone(), None, None, Origin::User, Box::new(StdoutErrorReporter),
+                ParserContextExtraData::default()));
+        }
+        stylesheets
+    };
+}
+
+lazy_static! {
+    pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet = {
+        match read_resource_file("quirks-mode.css") {
+            Ok(res) => {
+                Stylesheet::from_bytes(
+                    &res,
+                    Url::parse("chrome://resources/quirks-mode.css").unwrap(),
+                    None,
+                    None,
+                    Origin::UserAgent,
+                    Box::new(StdoutErrorReporter),
+                    ParserContextExtraData::default())
+            },
+            Err(..) => {
+                error!("Stylist failed to load 'quirks-mode.css'!");
+                process::exit(1);
+            }
+        }
+    };
+}
--- a/servo/components/style/stylesheets.rs
+++ b/servo/components/style/stylesheets.rs
@@ -8,21 +8,21 @@ use cssparser::{AtRuleParser, Parser, Qu
 use cssparser::{AtRuleType, RuleListParser, Token};
 use encoding::EncodingRef;
 use error_reporting::ParseErrorReporter;
 use font_face::{FontFaceRule, parse_font_face_block};
 use keyframes::{Keyframe, parse_keyframe_list};
 use media_queries::{Device, MediaQueryList, parse_media_query_list};
 use parser::{ParserContext, ParserContextExtraData, log_css_error};
 use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
-use selectors::parser::{Selector, SelectorImpl, parse_selector_list};
+use selector_impl::TheSelectorImpl;
+use selectors::parser::{Selector, parse_selector_list};
 use smallvec::SmallVec;
 use std::cell::Cell;
 use std::iter::Iterator;
-use std::marker::PhantomData;
 use std::slice;
 use string_cache::{Atom, Namespace};
 use url::Url;
 use viewport::ViewportRule;
 
 
 /// Each style rule has an origin, which determines where it enters the cascade.
 ///
@@ -38,107 +38,106 @@ pub enum Origin {
 
     /// http://dev.w3.org/csswg/css-cascade/#cascade-origin-user
     User,
 }
 
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct Stylesheet<Impl: SelectorImpl> {
+pub struct Stylesheet {
     /// List of rules in the order they were found (important for
     /// cascading order)
-    pub rules: Vec<CSSRule<Impl>>,
+    pub rules: Vec<CSSRule>,
     /// List of media associated with the Stylesheet, if any.
     pub media: Option<MediaQueryList>,
     pub origin: Origin,
     pub dirty_on_viewport_size_change: bool,
 }
 
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum CSSRule<Impl: SelectorImpl> {
+pub enum CSSRule {
     Charset(String),
     Namespace(Option<String>, Namespace),
-    Style(StyleRule<Impl>),
-    Media(MediaRule<Impl>),
+    Style(StyleRule),
+    Media(MediaRule),
     FontFace(FontFaceRule),
     Viewport(ViewportRule),
     Keyframes(KeyframesRule),
 }
 
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct KeyframesRule {
     pub name: Atom,
     pub keyframes: Vec<Keyframe>,
 }
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct MediaRule<Impl: SelectorImpl> {
+pub struct MediaRule {
     pub media_queries: MediaQueryList,
-    pub rules: Vec<CSSRule<Impl>>,
+    pub rules: Vec<CSSRule>,
 }
 
 
-impl<Impl: SelectorImpl> MediaRule<Impl> {
+impl MediaRule {
     #[inline]
     pub fn evaluate(&self, device: &Device) -> bool {
         self.media_queries.evaluate(device)
     }
 }
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct StyleRule<Impl: SelectorImpl> {
-    pub selectors: Vec<Selector<Impl>>,
+pub struct StyleRule {
+    pub selectors: Vec<Selector<TheSelectorImpl>>,
     pub declarations: PropertyDeclarationBlock,
 }
 
 
-impl<Impl: SelectorImpl> Stylesheet<Impl> {
+impl Stylesheet {
     pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
             input: I, base_url: Url, protocol_encoding_label: Option<&str>,
             environment_encoding: Option<EncodingRef>, origin: Origin,
             error_reporter: Box<ParseErrorReporter + Send>,
-            extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
+            extra_data: ParserContextExtraData) -> Stylesheet {
         let mut bytes = vec![];
         // TODO: incremental decoding and tokenization/parsing
         for chunk in input {
             bytes.extend_from_slice(&chunk)
         }
         Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label,
                                environment_encoding, origin, error_reporter,
                                extra_data)
     }
 
     pub fn from_bytes(bytes: &[u8],
                       base_url: Url,
                       protocol_encoding_label: Option<&str>,
                       environment_encoding: Option<EncodingRef>,
                       origin: Origin, error_reporter: Box<ParseErrorReporter + Send>,
                       extra_data: ParserContextExtraData)
-                      -> Stylesheet<Impl> {
+                      -> Stylesheet {
         // TODO: bytes.as_slice could be bytes.container_as_bytes()
         let (string, _) = decode_stylesheet_bytes(
             bytes, protocol_encoding_label, environment_encoding);
         Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data)
     }
 
     pub fn from_str(css: &str, base_url: Url, origin: Origin,
                     error_reporter: Box<ParseErrorReporter + Send>,
-                    extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
+                    extra_data: ParserContextExtraData) -> Stylesheet {
         let rule_parser = TopLevelRuleParser {
             context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter.clone(),
                                                         extra_data),
             state: Cell::new(State::Start),
-            _impl: PhantomData,
         };
         let mut input = Parser::new(css);
         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() {
@@ -184,55 +183,55 @@ impl<Impl: SelectorImpl> Stylesheet<Impl
     ///
     /// Always true if no associated MediaQueryList exists.
     pub fn is_effective_for_device(&self, device: &Device) -> bool {
         self.media.as_ref().map_or(true, |ref media| media.evaluate(device))
     }
 
     /// Return an iterator over all the rules within the style-sheet.
     #[inline]
-    pub fn rules(&self) -> Rules<Impl> {
+    pub fn rules(&self) -> Rules {
         Rules::new(self.rules.iter(), None)
     }
 
     /// Return an iterator over the effective rules within the style-sheet, as
     /// according to the supplied `Device`.
     ///
     /// If a condition does not hold, its associated conditional group rule and
     /// nested rules will be skipped. Use `rules` if all rules need to be
     /// examined.
     #[inline]
-    pub fn effective_rules<'a>(&'a self, device: &'a Device) -> Rules<'a, Impl> {
+    pub fn effective_rules<'a>(&'a self, device: &'a Device) -> Rules<'a> {
         Rules::new(self.rules.iter(), Some(device))
     }
 }
 
 /// `CSSRule` iterator.
 ///
 /// The iteration order is pre-order. Specifically, this implies that a
 /// conditional group rule will come before its nested rules.
-pub struct Rules<'a, Impl: SelectorImpl + 'a> {
+pub struct Rules<'a> {
     // 2 because normal case is likely to be just one level of nesting (@media)
-    stack: SmallVec<[slice::Iter<'a, CSSRule<Impl>>; 2]>,
+    stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]>,
     device: Option<&'a Device>
 }
 
-impl<'a, Impl: SelectorImpl + 'a> Rules<'a, Impl> {
-    fn new(iter: slice::Iter<'a, CSSRule<Impl>>, device: Option<&'a Device>) -> Rules<'a, Impl> {
-        let mut stack: SmallVec<[slice::Iter<'a, CSSRule<Impl>>; 2]> = SmallVec::new();
+impl<'a> Rules<'a> {
+    fn new(iter: slice::Iter<'a, CSSRule>, device: Option<&'a Device>) -> Rules<'a> {
+        let mut stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]> = SmallVec::new();
         stack.push(iter);
 
         Rules { stack: stack, device: device }
     }
 }
 
-impl<'a, Impl: SelectorImpl + 'a> Iterator for Rules<'a, Impl> {
-    type Item = &'a CSSRule<Impl>;
+impl<'a> Iterator for Rules<'a> {
+    type Item = &'a CSSRule;
 
-    fn next(&mut self) -> Option<&'a CSSRule<Impl>> {
+    fn next(&mut self) -> Option<&'a CSSRule> {
         while !self.stack.is_empty() {
             let top = self.stack.len() - 1;
             while let Some(rule) = self.stack[top].next() {
                 // handle conditional group rules
                 if let &CSSRule::Media(ref rule) = rule {
                     if let Some(device) = self.device {
                         if rule.evaluate(device) {
                             self.stack.push(rule.rules.iter());
@@ -257,44 +256,43 @@ impl<'a, Impl: SelectorImpl + 'a> Iterat
         // TODO: track total number of rules in style-sheet for upper bound?
         (0, None)
     }
 }
 
 pub mod rule_filter {
     //! Specific `CSSRule` variant iterators.
 
-    use selectors::parser::SelectorImpl;
     use std::marker::PhantomData;
     use super::super::font_face::FontFaceRule;
     use super::super::viewport::ViewportRule;
     use super::{CSSRule, KeyframesRule, MediaRule, StyleRule};
 
     macro_rules! rule_filter {
         ($variant:ident -> $value:ty) => {
             /// An iterator that only yields rules that are of the synonymous `CSSRule` variant.
             #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
             pub struct $variant<'a, I> {
                 iter: I,
                 _lifetime: PhantomData<&'a ()>
             }
 
-            impl<'a, I, Impl: SelectorImpl + 'a> $variant<'a, I>
-                where I: Iterator<Item=&'a CSSRule<Impl>> {
+            impl<'a, I> $variant<'a, I>
+                where I: Iterator<Item=&'a CSSRule> {
                 #[inline]
                 pub fn new(iter: I) -> $variant<'a, I> {
                     $variant {
                         iter: iter,
                         _lifetime: PhantomData
                     }
                 }
             }
 
-            impl<'a, I, Impl: SelectorImpl + 'a> Iterator for $variant<'a, I>
-                where I: Iterator<Item=&'a CSSRule<Impl>> {
+            impl<'a, I> Iterator for $variant<'a, I>
+                where I: Iterator<Item=&'a CSSRule> {
                 type Item = &'a $value;
 
                 fn next(&mut self) -> Option<&'a $value> {
                     while let Some(rule) = self.iter.next() {
                         match *rule {
                             CSSRule::$variant(ref value) => return Some(value),
                             _ => continue
                         }
@@ -305,42 +303,42 @@ pub mod rule_filter {
                 #[inline]
                 fn size_hint(&self) -> (usize, Option<usize>) {
                     (0, self.iter.size_hint().1)
                 }
             }
         }
     }
 
-    rule_filter!(Media -> MediaRule<Impl>);
-    rule_filter!(Style -> StyleRule<Impl>);
+    rule_filter!(Media -> MediaRule);
+    rule_filter!(Style -> StyleRule);
     rule_filter!(FontFace -> FontFaceRule);
     rule_filter!(Viewport -> ViewportRule);
     rule_filter!(Keyframes -> KeyframesRule);
 }
 
 /// Extension methods for `CSSRule` iterators.
-pub trait CSSRuleIteratorExt<'a, Impl: SelectorImpl + 'a>: Iterator<Item=&'a CSSRule<Impl>> + Sized {
+pub trait CSSRuleIteratorExt<'a>: Iterator<Item=&'a CSSRule> + Sized {
     /// Yield only @font-face rules.
     fn font_face(self) -> rule_filter::FontFace<'a, Self>;
 
     /// Yield only @media rules.
     fn media(self) -> rule_filter::Media<'a, Self>;
 
     /// Yield only style rules.
     fn style(self) -> rule_filter::Style<'a, Self>;
 
     /// Yield only @viewport rules.
     fn viewport(self) -> rule_filter::Viewport<'a, Self>;
 
     /// Yield only @keyframes rules.
     fn keyframes(self) -> rule_filter::Keyframes<'a, Self>;
 }
 
-impl<'a, I, Impl: SelectorImpl + 'a> CSSRuleIteratorExt<'a, Impl> for I where I: Iterator<Item=&'a CSSRule<Impl>> {
+impl<'a, I> CSSRuleIteratorExt<'a> for I where I: Iterator<Item=&'a CSSRule> {
     #[inline]
     fn font_face(self) -> rule_filter::FontFace<'a, I> {
         rule_filter::FontFace::new(self)
     }
 
     #[inline]
     fn media(self) -> rule_filter::Media<'a, I> {
         rule_filter::Media::new(self)
@@ -357,41 +355,37 @@ impl<'a, I, Impl: SelectorImpl + 'a> CSS
     }
 
     #[inline]
     fn keyframes(self) -> rule_filter::Keyframes<'a, I> {
         rule_filter::Keyframes::new(self)
     }
 }
 
-fn parse_nested_rules<Impl: SelectorImpl>(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule<Impl>> {
+fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule> {
     let mut iter = RuleListParser::new_for_nested_rule(input,
-                                                       NestedRuleParser {
-                                                           context: context,
-                                                           _impl: PhantomData
-                                                       });
+                                                       NestedRuleParser { context: context });
     let mut rules = Vec::new();
     while let Some(result) = iter.next() {
         match result {
             Ok(rule) => rules.push(rule),
             Err(range) => {
                 let pos = range.start;
                 let message = format!("Unsupported rule: '{}'", iter.input.slice(range));
                 log_css_error(iter.input, pos, &*message, &context);
             }
         }
     }
     rules
 }
 
 
-struct TopLevelRuleParser<'a, Impl: SelectorImpl> {
+struct TopLevelRuleParser<'a> {
     context: ParserContext<'a>,
     state: Cell<State>,
-    _impl: PhantomData<Impl>
 }
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
 enum State {
     Start = 1,
     Imports = 2,
     Namespaces = 3,
     Body = 4,
@@ -405,22 +399,22 @@ enum AtRulePrelude {
     Media(MediaQueryList),
     /// A @viewport rule prelude.
     Viewport,
     /// A @keyframes rule, with its animation name.
     Keyframes(Atom),
 }
 
 
-impl<'a, Impl: SelectorImpl> AtRuleParser for TopLevelRuleParser<'a, Impl> {
+impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
     type Prelude = AtRulePrelude;
-    type AtRule = CSSRule<Impl>;
+    type AtRule = CSSRule;
 
     fn parse_prelude(&self, name: &str, input: &mut Parser)
-                     -> Result<AtRuleType<AtRulePrelude, CSSRule<Impl>>, ()> {
+                     -> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
         match_ignore_ascii_case! { name,
             "charset" => {
                 if self.state.get() <= State::Start {
                     // Valid @charset rules are just ignored
                     self.state.set(State::Imports);
                     let charset = try!(input.expect_string()).into_owned();
                     return Ok(AtRuleType::WithoutBlock(CSSRule::Charset(charset)))
                 } else {
@@ -446,56 +440,55 @@ impl<'a, Impl: SelectorImpl> AtRuleParse
                 } else {
                     return Err(())  // "@namespace must be before any rule but @charset and @import"
                 }
             },
             _ => {}
         }
 
         self.state.set(State::Body);
-        AtRuleParser::parse_prelude(&NestedRuleParser { context: &self.context, _impl: PhantomData }, name, input)
+        AtRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, name, input)
     }
 
     #[inline]
-    fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
-        AtRuleParser::parse_block(&NestedRuleParser { context: &self.context, _impl: PhantomData }, prelude, input)
+    fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
+        AtRuleParser::parse_block(&NestedRuleParser { context: &self.context }, prelude, input)
     }
 }
 
 
-impl<'a, Impl: SelectorImpl> QualifiedRuleParser for TopLevelRuleParser<'a, Impl> {
-    type Prelude = Vec<Selector<Impl>>;
-    type QualifiedRule = CSSRule<Impl>;
+impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
+    type Prelude = Vec<Selector<TheSelectorImpl>>;
+    type QualifiedRule = CSSRule;
 
     #[inline]
-    fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<Impl>>, ()> {
+    fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<TheSelectorImpl>>, ()> {
         self.state.set(State::Body);
-        QualifiedRuleParser::parse_prelude(&NestedRuleParser { context: &self.context, _impl: PhantomData }, input)
+        QualifiedRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, input)
     }
 
     #[inline]
-    fn parse_block(&self, prelude: Vec<Selector<Impl>>, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
-        QualifiedRuleParser::parse_block(&NestedRuleParser { context: &self.context, _impl: PhantomData },
+    fn parse_block(&self, prelude: Vec<Selector<TheSelectorImpl>>, input: &mut Parser) -> Result<CSSRule, ()> {
+        QualifiedRuleParser::parse_block(&NestedRuleParser { context: &self.context },
                                          prelude, input)
     }
 }
 
 
-struct NestedRuleParser<'a, 'b: 'a, Impl: SelectorImpl> {
+struct NestedRuleParser<'a, 'b: 'a> {
     context: &'a ParserContext<'b>,
-    _impl: PhantomData<Impl>,
 }
 
 
-impl<'a, 'b, Impl: SelectorImpl> AtRuleParser for NestedRuleParser<'a, 'b, Impl> {
+impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
     type Prelude = AtRulePrelude;
-    type AtRule = CSSRule<Impl>;
+    type AtRule = CSSRule;
 
     fn parse_prelude(&self, name: &str, input: &mut Parser)
-                     -> Result<AtRuleType<AtRulePrelude, CSSRule<Impl>>, ()> {
+                     -> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
         match_ignore_ascii_case! { name,
             "media" => {
                 let media_queries = parse_media_query_list(input);
                 Ok(AtRuleType::WithBlock(AtRulePrelude::Media(media_queries)))
             },
             "font-face" => {
                 Ok(AtRuleType::WithBlock(AtRulePrelude::FontFace))
             },
@@ -514,17 +507,17 @@ impl<'a, 'b, Impl: SelectorImpl> AtRuleP
                 };
 
                 Ok(AtRuleType::WithBlock(AtRulePrelude::Keyframes(Atom::from(name))))
             },
             _ => Err(())
         }
     }
 
-    fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
+    fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
         match prelude {
             AtRulePrelude::FontFace => {
                 parse_font_face_block(self.context, input).map(CSSRule::FontFace)
             }
             AtRulePrelude::Media(media_queries) => {
                 Ok(CSSRule::Media(MediaRule {
                     media_queries: media_queries,
                     rules: parse_nested_rules(self.context, input),
@@ -538,23 +531,23 @@ impl<'a, 'b, Impl: SelectorImpl> AtRuleP
                     name: name,
                     keyframes: parse_keyframe_list(&self.context, input),
                 }))
             }
         }
     }
 }
 
-impl<'a, 'b, Impl: SelectorImpl> QualifiedRuleParser for NestedRuleParser<'a, 'b, Impl> {
-    type Prelude = Vec<Selector<Impl>>;
-    type QualifiedRule = CSSRule<Impl>;
+impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
+    type Prelude = Vec<Selector<TheSelectorImpl>>;
+    type QualifiedRule = CSSRule;
 
-    fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<Impl>>, ()> {
+    fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<TheSelectorImpl>>, ()> {
         parse_selector_list(&self.context.selector_context, input)
     }
 
-    fn parse_block(&self, prelude: Vec<Selector<Impl>>, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
+    fn parse_block(&self, prelude: Vec<Selector<TheSelectorImpl>>, input: &mut Parser) -> Result<CSSRule, ()> {
         Ok(CSSRule::Style(StyleRule {
             selectors: prelude,
             declarations: parse_property_declaration_list(self.context, input)
         }))
     }
 }
--- a/servo/components/style/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -41,21 +41,21 @@ pub type Generation = u32;
 /// this happens, the thread local bloom filter will be thrown away and rebuilt.
 thread_local!(
     static STYLE_BLOOM: RefCell<Option<(Box<BloomFilter>, UnsafeNode, Generation)>> = RefCell::new(None));
 
 /// Returns the thread local bloom filter.
 ///
 /// If one does not exist, a new one will be made for you. If it is out of date,
 /// it will be cleared and reused.
-fn take_thread_local_bloom_filter<N, Impl: SelectorImplExt>(parent_node: Option<N>,
-                                                            root: OpaqueNode,
-                                                            context: &SharedStyleContext<Impl>)
-                                                            -> Box<BloomFilter>
-                                                            where N: TNode {
+fn take_thread_local_bloom_filter<N>(parent_node: Option<N>,
+                                     root: OpaqueNode,
+                                     context: &SharedStyleContext)
+                                     -> Box<BloomFilter>
+                                     where N: TNode {
     STYLE_BLOOM.with(|style_bloom| {
         match (parent_node, style_bloom.borrow_mut().take()) {
             // Root node. Needs new bloom filter.
             (None,     _  ) => {
                 debug!("[{}] No parent, but new bloom filter!", tid());
                 Box::new(BloomFilter::new())
             }
             // No bloom filter for this thread yet.
@@ -77,19 +77,18 @@ fn take_thread_local_bloom_filter<N, Imp
                     insert_ancestors_into_bloom_filter(&mut bloom_filter, parent, root);
                 }
                 bloom_filter
             },
         }
     })
 }
 
-fn put_thread_local_bloom_filter<Impl: SelectorImplExt>(bf: Box<BloomFilter>,
-                                                        unsafe_node: &UnsafeNode,
-                                                        context: &SharedStyleContext<Impl>) {
+fn put_thread_local_bloom_filter(bf: Box<BloomFilter>, unsafe_node: &UnsafeNode,
+                                 context: &SharedStyleContext) {
     STYLE_BLOOM.with(move |style_bloom| {
         assert!(style_bloom.borrow().is_none(),
                 "Putting into a never-taken thread-local bloom filter");
         *style_bloom.borrow_mut() = Some((bf, *unsafe_node, context.generation));
     })
 }
 
 /// "Ancestors" in this context is inclusive of ourselves.
@@ -106,20 +105,19 @@ fn insert_ancestors_into_bloom_filter<N>
         n = match n.layout_parent_node(root) {
             None => break,
             Some(p) => p,
         };
     }
     debug!("[{}] Inserted {} ancestors.", tid(), ancestors);
 }
 
-pub fn remove_from_bloom_filter<'a, N, C, Impl>(context: &C, root: OpaqueNode, node: N)
+pub fn remove_from_bloom_filter<'a, N, C>(context: &C, root: OpaqueNode, node: N)
     where N: TNode,
-          Impl: SelectorImplExt + 'a,
-          C: StyleContext<'a, Impl>
+          C: StyleContext<'a>
 {
     let unsafe_layout_node = node.to_unsafe();
 
     let (mut bf, old_node, old_generation) =
         STYLE_BLOOM.with(|style_bloom| {
             style_bloom.borrow_mut()
                        .take()
                        .expect("The bloom filter should have been set by style recalc.")
@@ -153,18 +151,18 @@ pub trait DomTraversalContext<N: TNode> 
 
 /// Calculates the style for a single node.
 #[inline]
 #[allow(unsafe_code)]
 pub fn recalc_style_at<'a, N, C>(context: &'a C,
                                  root: OpaqueNode,
                                  node: N)
     where N: TNode,
-          C: StyleContext<'a, <N::ConcreteElement as Element>::Impl>,
-          <N::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues=N::ConcreteComputedValues> + 'a {
+          C: StyleContext<'a>,
+          <N::ConcreteElement as Element>::Impl: SelectorImplExt + 'a {
     // Get the parent node.
     let parent_opt = match node.parent_node() {
         Some(parent) if parent.is_element() => Some(parent),
         _ => None,
     };
 
     // Get the style bloom filter.
     let mut bf = take_thread_local_bloom_filter(parent_opt, root, context.shared_context());
--- a/servo/components/style/values.rs
+++ b/servo/components/style/values.rs
@@ -100,17 +100,17 @@ pub mod specified {
     use euclid::size::Size2D;
     use parser::ParserContext;
     use std::ascii::AsciiExt;
     use std::cmp;
     use std::f32::consts::PI;
     use std::fmt;
     use std::ops::Mul;
     use style_traits::values::specified::AllowedNumericType;
-    use super::computed::{TContext, ToComputedValue};
+    use super::computed::{Context, ToComputedValue};
     use super::{CSSFloat, FONT_MEDIUM_PX, HasViewportPercentage, LocalToCss, NoViewportPercentage};
     use url::Url;
 
     impl NoViewportPercentage for i32 {}  // For PropertyDeclaration::Order
 
     #[derive(Clone, PartialEq, Debug)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct CSSColor {
@@ -1564,17 +1564,17 @@ pub mod specified {
             }
         }
     }
 
     impl ToComputedValue for Time {
         type ComputedValue = Time;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> Time {
+        fn to_computed_value(&self, _: &Context) -> Time {
             *self
         }
     }
 
     impl ToCss for Time {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             write!(dest, "{}s", self.0)
         }
@@ -1606,17 +1606,17 @@ pub mod specified {
             Number::parse_with_minimum(input, 1.0)
         }
     }
 
     impl ToComputedValue for Number {
         type ComputedValue = CSSFloat;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> CSSFloat { self.0 }
+        fn to_computed_value(&self, _: &Context) -> CSSFloat { self.0 }
     }
 
     impl ToCss for Number {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             self.0.to_css(dest)
         }
     }
 
@@ -1631,17 +1631,17 @@ pub mod specified {
             parse_number(input).map(Opacity)
         }
     }
 
     impl ToComputedValue for Opacity {
         type ComputedValue = CSSFloat;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> CSSFloat {
+        fn to_computed_value(&self, _: &Context) -> CSSFloat {
             if self.0 < 0.0 {
                 0.0
             } else if self.0 > 1.0 {
                 1.0
             } else {
                 self.0
             }
         }
@@ -1653,87 +1653,76 @@ pub mod specified {
         }
     }
 }
 
 pub mod computed {
     use app_units::Au;
     use euclid::size::Size2D;
     use properties::ComputedValues;
-    use properties::style_struct_traits::Font;
     use std::fmt;
     use super::LocalToCss;
     use super::specified::AngleOrCorner;
     use super::{CSSFloat, specified};
     use url::Url;
     pub use cssparser::Color as CSSColor;
     pub use super::specified::{Angle, BorderStyle, Time};
 
-    pub trait TContext {
-        type ConcreteComputedValues: ComputedValues;
-        fn is_root_element(&self) -> bool;
-        fn viewport_size(&self) -> Size2D<Au>;
-        fn inherited_style(&self) -> &Self::ConcreteComputedValues;
-        fn style(&self) -> &Self::ConcreteComputedValues;
-        fn mutate_style(&mut self) -> &mut Self::ConcreteComputedValues;
-    }
-
-    pub struct Context<'a, C: ComputedValues> {
+    pub struct Context<'a> {
         pub is_root_element: bool,
         pub viewport_size: Size2D<Au>,
-        pub inherited_style: &'a C,
+        pub inherited_style: &'a ComputedValues,
 
         /// Values access through this need to be in the properties "computed early":
         /// color, text-decoration, font-size, display, position, float, border-*-style, outline-style
-        pub style: C,
+        pub style: ComputedValues,
     }
 
-    impl<'a, C: ComputedValues> TContext for Context<'a, C> {
-        type ConcreteComputedValues = C;
-        fn is_root_element(&self) -> bool { self.is_root_element }
-        fn viewport_size(&self) -> Size2D<Au> { self.viewport_size }
-        fn inherited_style(&self) -> &C { &self.inherited_style }
-        fn style(&self) -> &C { &self.style }
-        fn mutate_style(&mut self) -> &mut C { &mut self.style }
+    impl<'a> Context<'a> {
+        pub fn is_root_element(&self) -> bool { self.is_root_element }
+        pub fn viewport_size(&self) -> Size2D<Au> { self.viewport_size }
+        pub fn inherited_style(&self) -> &ComputedValues { &self.inherited_style }
+        pub fn style(&self) -> &ComputedValues { &self.style }
+        pub fn mutate_style(&mut self) -> &mut ComputedValues { &mut self.style }
     }
 
     pub trait ToComputedValue {
         type ComputedValue;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> Self::ComputedValue;
+        fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue;
     }
 
     pub trait ComputedValueAsSpecified {}
 
     impl<T> ToComputedValue for T where T: ComputedValueAsSpecified + Clone {
         type ComputedValue = T;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> T {
+        fn to_computed_value(&self, _context: &Context) -> T {
             self.clone()
         }
     }
 
     impl ToComputedValue for specified::CSSColor {
         type ComputedValue = CSSColor;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> CSSColor {
+        fn to_computed_value(&self, _context: &Context) -> CSSColor {
             self.parsed
         }
     }
 
     impl ComputedValueAsSpecified for specified::BorderStyle {}
 
     impl ToComputedValue for specified::Length {
         type ComputedValue = Au;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> Au {
+        fn to_computed_value(&self, context: &Context) -> Au {
             match *self {
                 specified::Length::Absolute(length) => length,
                 specified::Length::Calc(calc) => calc.to_computed_value(context).length(),
                 specified::Length::FontRelative(length) =>
                     length.to_computed_value(context.style().get_font().clone_font_size(),
                                              context.style().root_font_size()),
                 specified::Length::ViewportPercentage(length) =>
                     length.to_computed_value(context.viewport_size()),
@@ -1818,17 +1807,17 @@ pub mod computed {
                 _ => unreachable!()
             }
         }
     }
 
     impl ToComputedValue for specified::CalcLengthOrPercentage {
         type ComputedValue = CalcLengthOrPercentage;
 
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> CalcLengthOrPercentage {
+        fn to_computed_value(&self, context: &Context) -> CalcLengthOrPercentage {
             let mut length = None;
 
             if let Some(absolute) = self.absolute {
                 length = Some(length.unwrap_or(Au(0)) + absolute);
             }
 
             for val in &[self.vw, self.vh, self.vmin, self.vmax] {
                 if let Some(val) = *val {
@@ -1857,17 +1846,17 @@ pub mod computed {
             BorderRadiusSize(Size2D::new(LengthOrPercentage::Length(Au(0)), LengthOrPercentage::Length(Au(0))))
         }
     }
 
     impl ToComputedValue for specified::BorderRadiusSize {
         type ComputedValue = BorderRadiusSize;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> BorderRadiusSize {
+        fn to_computed_value(&self, context: &Context) -> BorderRadiusSize {
             let w = self.0.width.to_computed_value(context);
             let h = self.0.height.to_computed_value(context);
             BorderRadiusSize(Size2D::new(w, h))
         }
     }
 
     impl ::cssparser::ToCss for BorderRadiusSize {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@@ -1912,17 +1901,17 @@ pub mod computed {
                 LengthOrPercentage::Calc(calc) => write!(f, "{:?}", calc),
             }
         }
     }
 
     impl ToComputedValue for specified::LengthOrPercentage {
         type ComputedValue = LengthOrPercentage;
 
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentage {
+        fn to_computed_value(&self, context: &Context) -> LengthOrPercentage {
             match *self {
                 specified::LengthOrPercentage::Length(value) => {
                     LengthOrPercentage::Length(value.to_computed_value(context))
                 }
                 specified::LengthOrPercentage::Percentage(value) => {
                     LengthOrPercentage::Percentage(value.0)
                 }
                 specified::LengthOrPercentage::Calc(calc) => {
@@ -1976,17 +1965,17 @@ pub mod computed {
             }
         }
     }
 
     impl ToComputedValue for specified::LengthOrPercentageOrAuto {
         type ComputedValue = LengthOrPercentageOrAuto;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentageOrAuto {
+        fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto {
             match *self {
                 specified::LengthOrPercentageOrAuto::Length(value) => {
                     LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
                 }
                 specified::LengthOrPercentageOrAuto::Percentage(value) => {
                     LengthOrPercentageOrAuto::Percentage(value.0)
                 }
                 specified::LengthOrPercentageOrAuto::Auto => {
@@ -2032,17 +2021,17 @@ pub mod computed {
             }
         }
     }
 
     impl ToComputedValue for specified::LengthOrPercentageOrAutoOrContent {
         type ComputedValue = LengthOrPercentageOrAutoOrContent;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentageOrAutoOrContent {
+        fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAutoOrContent {
             match *self {
                 specified::LengthOrPercentageOrAutoOrContent::Length(value) => {
                     LengthOrPercentageOrAutoOrContent::Length(value.to_computed_value(context))
                 },
                 specified::LengthOrPercentageOrAutoOrContent::Percentage(value) => {
                     LengthOrPercentageOrAutoOrContent::Percentage(value.0)
                 },
                 specified::LengthOrPercentageOrAutoOrContent::Calc(calc) => {
@@ -2090,17 +2079,17 @@ pub mod computed {
             }
         }
     }
 
     impl ToComputedValue for specified::LengthOrPercentageOrNone {
         type ComputedValue = LengthOrPercentageOrNone;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentageOrNone {
+        fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone {
             match *self {
                 specified::LengthOrPercentageOrNone::Length(value) => {
                     LengthOrPercentageOrNone::Length(value.to_computed_value(context))
                 }
                 specified::LengthOrPercentageOrNone::Percentage(value) => {
                     LengthOrPercentageOrNone::Percentage(value.0)
                 }
                 specified::LengthOrPercentageOrNone::Calc(calc) => {
@@ -2140,17 +2129,17 @@ pub mod computed {
             }
         }
     }
 
     impl ToComputedValue for specified::LengthOrNone {
         type ComputedValue = LengthOrNone;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrNone {
+        fn to_computed_value(&self, context: &Context) -> LengthOrNone {
             match *self {
                 specified::LengthOrNone::Length(specified::Length::Calc(calc)) => {
                     LengthOrNone::Length(calc.to_computed_value(context).length())
                 }
                 specified::LengthOrNone::Length(value) => {
                     LengthOrNone::Length(value.to_computed_value(context))
                 }
                 specified::LengthOrNone::None => {
@@ -2168,17 +2157,17 @@ pub mod computed {
             }
         }
     }
 
     impl ToComputedValue for specified::Image {
         type ComputedValue = Image;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> Image {
+        fn to_computed_value(&self, context: &Context) -> Image {
             match *self {
                 specified::Image::Url(ref url) => Image::Url(url.clone()),
                 specified::Image::LinearGradient(ref linear_gradient) => {
                     Image::LinearGradient(linear_gradient.to_computed_value(context))
                 }
             }
         }
     }
@@ -2267,17 +2256,17 @@ pub mod computed {
             Ok(())
         }
     }
 
     impl ToComputedValue for specified::LinearGradient {
         type ComputedValue = LinearGradient;
 
         #[inline]
-        fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LinearGradient {
+        fn to_computed_value(&self, context: &Context) -> LinearGradient {
             let specified::LinearGradient {
                 angle_or_corner,
                 ref stops
             } = *self;
             LinearGradient {
                 angle_or_corner: angle_or_corner,
                 stops: stops.iter().map(|stop| {
                     ColorStop {
--- a/servo/components/style/viewport.rs
+++ b/servo/components/style/viewport.rs
@@ -8,17 +8,17 @@
 //! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
 
 use app_units::Au;
 use cssparser::ToCss;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::{Size2D, TypedSize2D};
 use parser::{ParserContext, log_css_error};
-use properties::{ComputedValues, ServoComputedValues};
+use properties::ComputedValues;
 use std::ascii::AsciiExt;
 use std::fmt;
 use std::iter::Enumerate;
 use std::str::Chars;
 use style_traits::ViewportPx;
 use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
 use stylesheets::Origin;
 use values::computed::{Context, ToComputedValue};
@@ -641,18 +641,18 @@ impl MaybeNew for ViewportConstraints {
         // resolved against initial values
         let initial_viewport = Size2D::new(Au::from_f32_px(initial_viewport.width.get()),
                                            Au::from_f32_px(initial_viewport.height.get()));
 
 
         let context = Context {
             is_root_element: false,
             viewport_size: initial_viewport,
-            inherited_style: ServoComputedValues::initial_values(),
-            style: ServoComputedValues::initial_values().clone(),
+            inherited_style: ComputedValues::initial_values(),
+            style: ComputedValues::initial_values().clone(),
         };
 
         // DEVICE-ADAPT § 9.3 Resolving 'extend-to-zoom'
         let extend_width;
         let extend_height;
         if let Some(extend_zoom) = max!(initial_zoom, max_zoom) {
             let scale_factor = 1. / extend_zoom;
             extend_width = Some(initial_viewport.width.scale_by(scale_factor));
--- a/servo/docs/components/style.md
+++ b/servo/docs/components/style.md
@@ -134,17 +134,17 @@ pseudo-elements**.
 Feel free to ping @SimonSapin, @mbrubeck or @emilio on irc, and please mention
 that you didn't find it here so it can be added :)
 
 [style-doc]: http://doc.servo.org/style/index.html
 [wiki-styling-overview]: https://github.com/servo/servo/wiki/Styling-overview
 [stylo]: https://public.etherpad-mozilla.org/p/stylo
 [selector-impl]: http://doc.servo.org/selectors/parser/trait.SelectorImpl.html
 [selector-impl-ext]: http://doc.servo.org/style/selector_impl/trait.SelectorImplExt.html
-[servo-selector-impl]: http://doc.servo.org/style/selector_impl/struct.ServoSelectorImpl.html
+[servo-selector-impl]: http://doc.servo.org/style/servo_selector_impl/struct.ServoSelectorImpl.html
 [tree-structural-pseudo-classes]: https://www.w3.org/TR/selectors4/#structural-pseudos
 [style-dom-traits]: http://doc.servo.org/style/dom/index.html
 [layout-wrapper]: http://doc.servo.org/layout/wrapper/index.html
 [pseudo-cascade-type]: http://doc.servo.org/style/selector_impl/enum.PseudoElementCascadeType.html
 [servo-pseudo-elements]: http://doc.servo.org/style/selector_impl/enum.PseudoElement.html
 [mdn-pseudo-before]: https://developer.mozilla.org/en/docs/Web/CSS/::before
 [mdn-pseudo-after]: https://developer.mozilla.org/en/docs/Web/CSS/::after
 [mdn-pseudo-selection]: https://developer.mozilla.org/en/docs/Web/CSS/::selection
--- a/servo/ports/geckolib/Cargo.lock
+++ b/servo/ports/geckolib/Cargo.lock
@@ -1,14 +1,13 @@
 [root]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "app_units 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gecko_bindings 0.0.1",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -1,24 +1,21 @@
 [package]
 name = "geckoservo"
 version = "0.0.1"
 authors = ["The Servo Project Developers"]
 license = "MPL-2.0"
 
-build = "build.rs"
-
 [lib]
 name = "geckoservo"
 path = "lib.rs"
 crate-type = ["staticlib"]
 
 [dependencies]
 app_units = "0.2.5"
-cssparser = "0.5.4"
 env_logger = "0.3"
 euclid = "0.7.1"
 gecko_bindings = {version = "0.0.1", path = "gecko_bindings"}
 lazy_static = "0.2"
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 num_cpus = "0.2.2"
 selectors = "0.7"
deleted file mode 100644
--- a/servo/ports/geckolib/build.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-/* 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 std::env;
-use std::path::Path;
-use std::process::{Command, exit};
-
-#[cfg(windows)]
-fn find_python() -> String {
-    if Command::new("python2.7.exe").arg("--version").output().is_ok() {
-        return "python2.7.exe".to_owned();
-    }
-
-    if Command::new("python27.exe").arg("--version").output().is_ok() {
-        return "python27.exe".to_owned();
-    }
-
-    if Command::new("python.exe").arg("--version").output().is_ok() {
-        return "python.exe".to_owned();
-    }
-
-    panic!(concat!("Can't find python (tried python2.7.exe, python27.exe, and python.exe)! ",
-                   "Try fixing PATH or setting the PYTHON env var"));
-}
-
-#[cfg(not(windows))]
-fn find_python() -> String {
-    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
-        "python2.7"
-    } else {
-        "python"
-    }.to_owned()
-}
-
-fn main() {
-    let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
-
-    // Mako refuses to load templates outside the scope of the current working directory,
-    // so we need to run it from the top source directory.
-    let geckolib_dir = Path::new(file!()).parent().unwrap();
-    let top_dir = geckolib_dir.join("..").join("..");
-
-    let properties_dir = Path::new("components").join("style").join("properties");
-    println!("cargo:rerun-if-changed={}", top_dir.join(&properties_dir).to_str().unwrap());
-    println!("cargo:rerun-if-changed={}", geckolib_dir.join("properties.mako.rs").to_str().unwrap());
-
-    let status = Command::new(python)
-        .current_dir(&top_dir)
-        .arg(&properties_dir.join("build.py"))
-        .arg("gecko")
-        .arg("geckolib")
-        .status()
-        .unwrap();
-    if !status.success() {
-        exit(1)
-    }
-}
--- a/servo/ports/geckolib/context.rs
+++ b/servo/ports/geckolib/context.rs
@@ -1,22 +1,20 @@
 /* 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 selector_impl::{GeckoSelectorImpl, SharedStyleContext};
+
 use std::cell::RefCell;
 use std::rc::Rc;
-use style::context::{LocalStyleContext, StyleContext};
+use style::context::{LocalStyleContext, StyleContext, SharedStyleContext};
 
-thread_local!(static LOCAL_CONTEXT_KEY:
-                RefCell<Option<Rc<LocalStyleContext<GeckoSelectorImpl>>>> = RefCell::new(None));
+thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalStyleContext>>> = RefCell::new(None));
 
 // Keep this implementation in sync with the one in components/layout/context.rs.
-fn create_or_get_local_context(shared: &SharedStyleContext)
-                               -> Rc<LocalStyleContext<GeckoSelectorImpl>> {
+fn create_or_get_local_context(shared: &SharedStyleContext) -> Rc<LocalStyleContext> {
     LOCAL_CONTEXT_KEY.with(|r| {
         let mut r = r.borrow_mut();
         if let Some(context) = r.clone() {
             if shared.screen_size_changed {
                 context.applicable_declarations_cache.borrow_mut().evict_all();
             }
             context
         } else {
@@ -24,30 +22,30 @@ fn create_or_get_local_context(shared: &
             *r = Some(context.clone());
             context
         }
     })
 }
 
 pub struct StandaloneStyleContext<'a> {
     pub shared: &'a SharedStyleContext,
-    cached_local_context: Rc<LocalStyleContext<GeckoSelectorImpl>>,
+    cached_local_context: Rc<LocalStyleContext>,
 }
 
 impl<'a> StandaloneStyleContext<'a> {
     pub fn new(shared: &'a SharedStyleContext) -> Self {
         let local_context = create_or_get_local_context(shared);
         StandaloneStyleContext {
             shared: shared,
             cached_local_context: local_context,
         }
     }
 }
 
-impl<'a> StyleContext<'a, GeckoSelectorImpl> for StandaloneStyleContext<'a> {
+impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
     fn shared_context(&self) -> &'a SharedStyleContext {
         &self.shared
     }
 
-    fn local_context(&self) -> &LocalStyleContext<GeckoSelectorImpl> {
+    fn local_context(&self) -> &LocalStyleContext {
         &self.cached_local_context
     }
 }
--- a/servo/ports/geckolib/data.rs
+++ b/servo/ports/geckolib/data.rs
@@ -1,25 +1,28 @@
 /* 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 euclid::Size2D;
 use euclid::size::TypedSize2D;
 use gecko_bindings::bindings::RawServoStyleSet;
 use num_cpus;
-use selector_impl::{Animation, SharedStyleContext, Stylist, Stylesheet};
 use std::cmp;
 use std::collections::HashMap;
 use std::env;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::sync::{Arc, RwLock};
+use style::animation::Animation;
+use style::context::SharedStyleContext;
 use style::dom::OpaqueNode;
 use style::media_queries::{Device, MediaType};
 use style::parallel::WorkQueueData;
+use style::selector_matching::Stylist;
+use style::stylesheets::Stylesheet;
 use style::workqueue::WorkQueue;
 use style_traits::ViewportPx;
 use util::thread_state;
 
 pub struct PerDocumentStyleData {
     /// Rule processor.
     pub stylist: Arc<Stylist>,
 
deleted file mode 100644
--- a/servo/ports/geckolib/generate_properties_rs.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/.
-
-import os
-import sys
-
-from mako import exceptions
-from mako.template import Template
-
-try:
-    style_template = Template(filename=os.environ['STYLE_TEMPLATE'],
-                              input_encoding='utf8')
-    style_template.render(PRODUCT='gecko')
-
-    geckolib_template = Template(filename=os.environ['GECKOLIB_TEMPLATE'], input_encoding='utf8')
-    output = geckolib_template.render(STYLE_STRUCTS=style_template.module.STYLE_STRUCTS,
-                                      to_rust_ident=style_template.module.to_rust_ident)
-    print(output.encode('utf8'))
-except:
-    sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
-    sys.exit(1)
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -9,34 +9,33 @@ use data::{NUM_THREADS, PerDocumentStyle
 use env_logger;
 use euclid::Size2D;
 use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
 use gecko_bindings::bindings::{RawServoStyleSet, RawServoStyleSheet, ServoComputedValues};
 use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
 use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
 use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
 use gecko_bindings::structs::{SheetParsingMode, nsIAtom};
-use properties::GeckoComputedValues;
-use selector_impl::{GeckoSelectorImpl, PseudoElement, SharedStyleContext, Stylesheet};
-use std::marker::PhantomData;
-use std::mem::{forget, transmute};
+use std::mem::transmute;
 use std::ptr;
 use std::slice;
 use std::str::from_utf8_unchecked;
 use std::sync::{Arc, Mutex};
 use style::arc_ptr_eq;
-use style::context::{LocalStyleContextCreationInfo, ReflowGoal};
+use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
 use style::dom::{TDocument, TElement, TNode};
 use style::error_reporting::StdoutErrorReporter;
+use style::gecko_glue::ArcHelpers;
+use style::gecko_selector_impl::{GeckoSelectorImpl, PseudoElement};
 use style::parallel;
 use style::parser::ParserContextExtraData;
 use style::properties::{ComputedValues, PropertyDeclarationBlock, parse_one_declaration};
 use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType};
 use style::sequential;
-use style::stylesheets::Origin;
+use style::stylesheets::{Stylesheet, Origin};
 use traversal::RecalcStyleOnly;
 use url::Url;
 use wrapper::{DUMMY_BASE_URL, GeckoDocument, GeckoElement, GeckoNode, NonOpaqueStyleData};
 
 // TODO: This is ugly and should go away once we get an atom back-end.
 pub fn pseudo_element_from_atom(pseudo: *mut nsIAtom,
                                 in_ua_stylesheet: bool) -> Result<PseudoElement, String> {
     use gecko_bindings::bindings::Gecko_GetAtomAsUTF16;
@@ -82,17 +81,17 @@ fn restyle_subtree(node: GeckoNode, raw_
 
     // Force the creation of our lazily-constructed initial computed values on
     // the main thread, since it's not safe to call elsewhere.
     //
     // FIXME(bholley): this should move into Servo_Initialize as soon as we get
     // rid of the HackilyFindSomeDeviceContext stuff that happens during
     // initial_values computation, since that stuff needs to be called further
     // along in startup than the sensible place to call Servo_Initialize.
-    GeckoComputedValues::initial_values();
+    ComputedValues::initial_values();
 
     let _needs_dirtying = Arc::get_mut(&mut per_doc_data.stylist).unwrap()
                               .update(&per_doc_data.stylesheets,
                                       per_doc_data.stylesheets_changed);
     per_doc_data.stylesheets_changed = false;
 
     let local_context_data =
         LocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
@@ -173,64 +172,16 @@ pub extern "C" fn Servo_StylesheetFromUT
     };
     let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter),
                                               extra_data));
     unsafe {
         transmute(sheet)
     }
 }
 
-pub struct ArcHelpers<GeckoType, ServoType> {
-    phantom1: PhantomData<GeckoType>,
-    phantom2: PhantomData<ServoType>,
-}
-
-
-impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
-    pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
-                           where F: FnOnce(&Arc<ServoType>) -> Output {
-        debug_assert!(!raw.is_null());
-
-        let owned = unsafe { Self::into(raw) };
-        let result = cb(&owned);
-        forget(owned);
-        result
-    }
-
-    pub fn maybe_with<F, Output>(maybe_raw: *mut GeckoType, cb: F) -> Output
-                                 where F: FnOnce(Option<&Arc<ServoType>>) -> Output {
-        let owned = if maybe_raw.is_null() {
-            None
-        } else {
-            Some(unsafe { Self::into(maybe_raw) })
-        };
-
-        let result = cb(owned.as_ref());
-        forget(owned);
-
-        result
-    }
-
-    pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
-        transmute(ptr)
-    }
-
-    pub fn from(owned: Arc<ServoType>) -> *mut GeckoType {
-        unsafe { transmute(owned) }
-    }
-
-    pub unsafe fn addref(ptr: *mut GeckoType) {
-        Self::with(ptr, |arc| forget(arc.clone()));
-    }
-
-    pub unsafe fn release(ptr: *mut GeckoType) {
-        let _ = Self::into(ptr);
-    }
-}
-
 #[no_mangle]
 pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut RawServoStyleSheet,
                                          raw_data: *mut RawServoStyleSet) {
     type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
     Helpers::with(raw_sheet, |sheet| {
         data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
         data.stylesheets.push(sheet.clone());
@@ -302,17 +253,17 @@ pub extern "C" fn Servo_GetComputedValue
     let arc_cv = match node.borrow_data().map_or(None, |data| data.style.clone()) {
         Some(style) => style,
         None => {
             // FIXME(bholley): This case subverts the intended semantics of this
             // function, and exists only to make stylo builds more robust corner-
             // cases where Gecko wants the style for a node that Servo never
             // traversed. We should remove this as soon as possible.
             error!("stylo: encountered unstyled node, substituting default values.");
-            Arc::new(GeckoComputedValues::initial_values().clone())
+            Arc::new(ComputedValues::initial_values().clone())
         },
     };
     unsafe { transmute(arc_cv) }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: *mut ServoComputedValues,
                                                          pseudo_tag: *mut nsIAtom,
@@ -323,17 +274,17 @@ pub extern "C" fn Servo_GetComputedValue
     let pseudo = match pseudo_element_from_atom(pseudo_tag, /* ua_stylesheet = */ true) {
         Ok(pseudo) => pseudo,
         Err(pseudo) => {
             warn!("stylo: Unable to parse anonymous-box pseudo-element: {}", pseudo);
             return ptr::null_mut();
         }
     };
 
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
+    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
 
     Helpers::maybe_with(parent_style_or_null, |maybe_parent| {
         let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent);
         new_computed.map_or(ptr::null_mut(), |c| Helpers::from(c))
     })
 }
 
 #[no_mangle]
@@ -362,17 +313,17 @@ pub extern "C" fn Servo_GetComputedValue
         }
     };
 
 
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
 
     let element = unsafe { GeckoElement::from_raw(match_element) };
 
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
+    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
 
     match GeckoSelectorImpl::pseudo_element_cascade_type(&pseudo) {
         PseudoElementCascadeType::Eager => {
             let node = element.as_node();
             let maybe_computed = node.borrow_data()
                                      .and_then(|data| {
                                          data.per_pseudo.get(&pseudo).map(|c| c.clone())
                                      });
@@ -390,32 +341,32 @@ pub extern "C" fn Servo_GetComputedValue
                          Servo_GetComputedValuesForPseudoElement");
         }
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_InheritComputedValues(parent_style: *mut ServoComputedValues)
      -> *mut ServoComputedValues {
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
+    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
     Helpers::with(parent_style, |parent| {
-        let style = GeckoComputedValues::inherit_from(parent);
+        let style = ComputedValues::inherit_from(parent);
         Helpers::from(style)
     })
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_AddRefComputedValues(ptr: *mut ServoComputedValues) -> () {
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
+    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
     unsafe { Helpers::addref(ptr) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ReleaseComputedValues(ptr: *mut ServoComputedValues) -> () {
-    type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
+    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
     unsafe { Helpers::release(ptr) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_InitStyleSet() -> *mut RawServoStyleSet {
     let data = Box::new(PerDocumentStyleData::new());
     Box::into_raw(data) as *mut RawServoStyleSet
 }
--- a/servo/ports/geckolib/lib.rs
+++ b/servo/ports/geckolib/lib.rs
@@ -1,15 +1,13 @@
 /* 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/. */
 
 extern crate app_units;
-#[macro_use]
-extern crate cssparser;
 extern crate env_logger;
 extern crate euclid;
 extern crate gecko_bindings;
 #[macro_use]
 extern crate lazy_static;
 extern crate libc;
 #[macro_use]
 extern crate log;
@@ -21,23 +19,14 @@ extern crate style;
 extern crate style_traits;
 extern crate url;
 extern crate util;
 
 mod context;
 mod data;
 #[allow(non_snake_case)]
 pub mod glue;
-mod selector_impl;
 mod traversal;
-mod values;
 mod wrapper;
 
-// Generated from the properties.mako.rs template by build.rs
-#[macro_use]
-#[allow(unsafe_code)]
-pub mod properties {
-    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
-}
-
 // FIXME(bholley): This should probably go away once we harmonize the allocators.
 #[no_mangle]
 pub extern "C" fn je_malloc_usable_size(_: *const ::libc::c_void) -> ::libc::size_t { 0 }
--- a/servo/ports/geckolib/traversal.rs
+++ b/servo/ports/geckolib/traversal.rs
@@ -1,15 +1,15 @@
 /* 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 context::StandaloneStyleContext;
-use selector_impl::SharedStyleContext;
 use std::mem;
+use style::context::SharedStyleContext;
 use style::dom::OpaqueNode;
 use style::traversal::{DomTraversalContext, recalc_style_at};
 use wrapper::GeckoNode;
 
 pub struct RecalcStyleOnly<'lc> {
     context: StandaloneStyleContext<'lc>,
     root: OpaqueNode,
 }
--- a/servo/ports/geckolib/wrapper.rs
+++ b/servo/ports/geckolib/wrapper.rs
@@ -22,36 +22,36 @@ use gecko_bindings::bindings::{Gecko_IsL
 use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
 #[allow(unused_imports)] // Used in commented-out code.
 use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
 use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
 use gecko_bindings::structs::nsIAtom;
 use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
 use glue::GeckoDeclarationBlock;
 use libc::uintptr_t;
-use properties::GeckoComputedValues;
-use selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PrivateStyleData};
 use selectors::Element;
 use selectors::matching::DeclarationBlock;
 use selectors::parser::{AttrSelector, NamespaceConstraint};
 use std::marker::PhantomData;
 use std::ops::BitOr;
 use std::ptr;
 use std::slice;
 use std::sync::Arc;
 use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
+use style::data::PrivateStyleData;
 use style::dom::{OpaqueNode, PresentationalHintsSynthetizer};
 use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
 use style::element_state::ElementState;
 #[allow(unused_imports)] // Used in commented-out code.
 use style::error_reporting::StdoutErrorReporter;
+use style::gecko_selector_impl::{GeckoSelectorImpl, NonTSPseudoClass};
 #[allow(unused_imports)] // Used in commented-out code.
 use style::parser::ParserContextExtraData;
 #[allow(unused_imports)] // Used in commented-out code.
-use style::properties::parse_style_attribute;
+use style::properties::{ComputedValues, parse_style_attribute};
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
 use style::refcell::{Ref, RefCell, RefMut};
 use style::restyle_hints::ElementSnapshot;
 use style::selector_impl::ElementExt;
 use style::sink::Push;
 #[allow(unused_imports)] // Used in commented-out code.
 use url::Url;
 
@@ -94,32 +94,30 @@ impl<'ln> GeckoNode<'ln> {
             }
         }
     }
 }
 
 #[derive(Clone, Copy)]
 pub struct DummyRestyleDamage;
 impl TRestyleDamage for DummyRestyleDamage {
-    type ConcreteComputedValues = GeckoComputedValues;
-    fn compute(_: Option<&Arc<GeckoComputedValues>>, _: &GeckoComputedValues) -> Self { DummyRestyleDamage }
+    fn compute(_: Option<&Arc<ComputedValues>>, _: &ComputedValues) -> Self { DummyRestyleDamage }
     fn rebuild_and_reflow() -> Self { DummyRestyleDamage }
 }
 impl BitOr for DummyRestyleDamage {
     type Output = Self;
     fn bitor(self, _: Self) -> Self { DummyRestyleDamage }
 }
 
 
 
 impl<'ln> TNode for GeckoNode<'ln> {
     type ConcreteDocument = GeckoDocument<'ln>;
     type ConcreteElement = GeckoElement<'ln>;
     type ConcreteRestyleDamage = DummyRestyleDamage;
-    type ConcreteComputedValues = GeckoComputedValues;
 
     fn to_unsafe(&self) -> UnsafeNode {
         (self.node as usize, 0)
     }
 
     unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
         GeckoNode::from_raw(n.0 as *mut RawGeckoNode)
     }
--- a/servo/tests/unit/style/lib.rs
+++ b/servo/tests/unit/style/lib.rs
@@ -24,15 +24,15 @@ mod media_queries;
 mod properties;
 mod str;
 mod stylesheets;
 mod value;
 mod viewport;
 
 mod writing_modes {
     use style::logical_geometry::WritingMode;
-    use style::properties::{INITIAL_SERVO_VALUES, ComputedValues, get_writing_mode};
+    use style::properties::{INITIAL_SERVO_VALUES, get_writing_mode};
 
     #[test]
     fn initial_writing_mode_is_empty() {
         assert_eq!(get_writing_mode(INITIAL_SERVO_VALUES.get_inheritedbox()), WritingMode::empty())
     }
 }
--- a/servo/tests/unit/style/media_queries.rs
+++ b/servo/tests/unit/style/media_queries.rs
@@ -4,18 +4,17 @@
 
 use app_units::Au;
 use cssparser::{Parser, SourcePosition};
 use euclid::size::Size2D;
 use std::borrow::ToOwned;
 use style::error_reporting::ParseErrorReporter;
 use style::media_queries::*;
 use style::parser::ParserContextExtraData;
-use style::servo::Stylesheet;
-use style::stylesheets::{Origin, CSSRuleIteratorExt};
+use style::stylesheets::{Stylesheet, Origin, CSSRuleIteratorExt};
 use style::values::specified;
 use url::Url;
 
 pub struct CSSErrorReporterTest;
 
 impl ParseErrorReporter for CSSErrorReporterTest {
      fn report_error(&self, _input: &mut Parser, _position: SourcePosition, _message: &str) {
      }
--- a/servo/tests/unit/style/stylesheets.rs
+++ b/servo/tests/unit/style/stylesheets.rs
@@ -8,18 +8,17 @@ use selectors::parser::*;
 use std::borrow::ToOwned;
 use std::sync::Arc;
 use std::sync::Mutex;
 use string_cache::{Atom, Namespace};
 use style::error_reporting::ParseErrorReporter;
 use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
 use style::parser::ParserContextExtraData;
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands};
-use style::servo::Stylesheet;
-use style::stylesheets::{CSSRule, StyleRule, KeyframesRule, Origin};
+use style::stylesheets::{Stylesheet, CSSRule, StyleRule, KeyframesRule, Origin};
 use style::values::specified::{LengthOrPercentageOrAuto, Percentage};
 use url::Url;
 
 #[test]
 fn test_parse_stylesheet() {
     let css = r"
         @namespace url(http://www.w3.org/1999/xhtml);
         /* FIXME: only if scripting is enabled */
--- a/servo/tests/unit/style/viewport.rs
+++ b/servo/tests/unit/style/viewport.rs
@@ -4,18 +4,17 @@
 
 use cssparser::Parser;
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::Size2D;
 use media_queries::CSSErrorReporterTest;
 use style::error_reporting::ParseErrorReporter;
 use style::media_queries::{Device, MediaType};
 use style::parser::{ParserContext, ParserContextExtraData};
-use style::servo::Stylesheet;
-use style::stylesheets::{Origin, CSSRuleIteratorExt};
+use style::stylesheets::{Stylesheet, Origin, CSSRuleIteratorExt};
 use style::values::specified::Length::{self, ViewportPercentage};
 use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
 use style::values::specified::ViewportPercentageLength::Vw;
 use style::viewport::*;
 use style_traits::viewport::*;
 use url::Url;
 
 macro_rules! stylesheet {