Bug 1333923. Update webrender bcf3c371086894f5e1d098ee60f0592abf01f6b3. r=gfx?
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 25 Jan 2017 17:31:23 -0500
changeset 388816 b512c4f0d98b50b6c5eac0ff12f4d38d4390c6a7
parent 388815 4ff35aa906927bd471d9376792b2697725b48cc7
child 388817 e509d4d932780e6ad46b76f02a0955bd1279fb9d
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfx
bugs1333923
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1333923. Update webrender bcf3c371086894f5e1d098ee60f0592abf01f6b3. r=gfx?
README.webrender
gfx/webrender/Cargo.toml
gfx/webrender/src/frame.rs
gfx/webrender/src/layer.rs
gfx/webrender/src/lib.rs
gfx/webrender/src/platform/macos/font.rs
gfx/webrender/src/platform/unix/font.rs
gfx/webrender/src/platform/windows/font.rs
gfx/webrender/src/prim_store.rs
gfx/webrender/src/render_backend.rs
gfx/webrender/src/renderer.rs
gfx/webrender/src/resource_cache.rs
gfx/webrender/src/scroll_tree.rs
gfx/webrender/src/texture_cache.rs
gfx/webrender/src/tiling.rs
gfx/webrender/tests/angle_shader_validation.rs
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_traits/src/api.rs
gfx/webrender_traits/src/types.rs
third_party/rust/dwrote/.cargo-checksum.json
third_party/rust/dwrote/Cargo.toml
third_party/rust/dwrote/build.rs
third_party/rust/dwrote/src/bitmap_render_target.rs
third_party/rust/dwrote/src/font.rs
third_party/rust/dwrote/src/font_face.rs
third_party/rust/dwrote/src/gdi_interop.rs
third_party/rust/dwrote/src/glyph_run_analysis.rs
third_party/rust/dwrote/src/lib.rs
third_party/rust/dwrote/src/rendering_params.rs
third_party/rust/dwrote/src/types.rs
third_party/rust/gleam/.cargo-checksum.json
third_party/rust/gleam/Cargo.toml
third_party/rust/gleam/src/gl.rs
third_party/rust/offscreen_gl_context/.cargo-checksum.json
third_party/rust/offscreen_gl_context/Cargo.toml
third_party/rust/offscreen_gl_context/src/draw_buffer.rs
third_party/rust/offscreen_gl_context/src/gl_context.rs
third_party/rust/pkg-config/.cargo-checksum.json
third_party/rust/pkg-config/.travis.yml
third_party/rust/pkg-config/Cargo.toml
third_party/rust/pkg-config/README.md
third_party/rust/pkg-config/src/lib.rs
third_party/rust/pkg-config/tests/test.rs
third_party/rust/quote/.cargo-checksum.json
third_party/rust/quote/Cargo.toml
third_party/rust/quote/src/to_tokens.rs
third_party/rust/serde/.cargo-checksum.json
third_party/rust/serde/Cargo.toml
third_party/rust/serde_codegen/.cargo-checksum.json
third_party/rust/serde_codegen/Cargo.toml
third_party/rust/syn/.cargo-checksum.json
third_party/rust/syn/Cargo.toml
third_party/rust/syn/src/expr.rs
third_party/rust/syn/src/item.rs
third_party/rust/syn/src/lib.rs
third_party/rust/syn/src/mac.rs
third_party/rust/syn/src/nom.rs
third_party/rust/syn/src/ty.rs
third_party/rust/syn/src/visit.rs
third_party/rust/unicode-xid-0.0.3/.cargo-checksum.json
third_party/rust/unicode-xid-0.0.3/.cargo-ok
third_party/rust/unicode-xid-0.0.3/.gitignore
third_party/rust/unicode-xid-0.0.3/.travis.yml
third_party/rust/unicode-xid-0.0.3/COPYRIGHT
third_party/rust/unicode-xid-0.0.3/Cargo.toml
third_party/rust/unicode-xid-0.0.3/LICENSE-APACHE
third_party/rust/unicode-xid-0.0.3/LICENSE-MIT
third_party/rust/unicode-xid-0.0.3/README.md
third_party/rust/unicode-xid-0.0.3/scripts/unicode.py
third_party/rust/unicode-xid-0.0.3/src/lib.rs
third_party/rust/unicode-xid-0.0.3/src/tables.rs
third_party/rust/unicode-xid-0.0.3/src/tests.rs
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/README.webrender
+++ b/README.webrender
@@ -54,9 +54,9 @@ 8) Build and test. You may need to make 
    features yet, just get the build working with the minimal changes.
 9) Commit the changes locally from step 7, and push everything to the
    graphics branch.
 10) Now you have an update webrender with the new features you wanted,
    so you can write gecko code against them.
 
 Yes, this is somewhat painful. It used to be worse. :)
 
-Latest Commit: 6c15d14bb6b786cad979407e6ed7b86949b4ae48
+Latest Commit: bcf3c371086894f5e1d098ee60f0592abf01f6b3
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -25,16 +25,19 @@ lazy_static = "0.2"
 log = "0.3"
 num-traits = "0.1.32"
 offscreen_gl_context = {version = "0.5", features = ["serde_serialization", "osmesa"]}
 time = "0.1"
 threadpool = "1.3.2"
 webrender_traits = {path = "../webrender_traits", default-features = false}
 bitflags = "0.7"
 
+[dev-dependencies]
+angle = {git = "https://github.com/servo/angle", branch = "servo"}
+
 [target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies]
 freetype = { version = "0.2", default-features = false }
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.1.5"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-graphics = "0.5.0"
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -1,59 +1,47 @@
 /* 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 app_units::Au;
-use euclid::Point3D;
 use fnv::FnvHasher;
-use geometry::ray_intersects_rect;
 use internal_types::{ANGLE_FLOAT_TO_FIXED, AxisDirection};
 use internal_types::{CompositionOp};
 use internal_types::{LowLevelFilterOp};
 use internal_types::{RendererFrame};
-use layer::{Layer, ScrollingState};
+use layer::Layer;
 use resource_cache::ResourceCache;
 use scene::Scene;
-use std::collections::{HashMap, HashSet};
+use scroll_tree::{ScrollTree, ScrollStates};
+use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
-use tiling::{AuxiliaryListsMap, FrameBuilder, FrameBuilderConfig, LayerMap, PrimitiveFlags};
-use webrender_traits::{AuxiliaryLists, PipelineId, Epoch, ScrollPolicy, ScrollLayerId};
-use webrender_traits::{ClipRegion, ColorF, DisplayItem, StackingContext, FilterOp, MixBlendMode};
-use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, ScrollLocation, SpecificDisplayItem, ScrollLayerState};
-use webrender_traits::{LayerRect, LayerPoint, LayerSize};
-use webrender_traits::{ServoScrollRootId, ScrollLayerRect, as_scroll_parent_rect, ScrollLayerPixel};
-use webrender_traits::{WorldPoint, WorldPoint4D};
-use webrender_traits::{LayerToScrollTransform, ScrollToWorldTransform};
-
-#[cfg(target_os = "macos")]
-const CAN_OVERSCROLL: bool = true;
-
-#[cfg(not(target_os = "macos"))]
-const CAN_OVERSCROLL: bool = false;
+use tiling::{AuxiliaryListsMap, FrameBuilder, FrameBuilderConfig, PrimitiveFlags};
+use webrender_traits::{AuxiliaryLists, ClipRegion, ColorF, DisplayItem, Epoch, FilterOp};
+use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
+use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerState};
+use webrender_traits::{ScrollLocation, ScrollPolicy, ServoScrollRootId, SpecificDisplayItem};
+use webrender_traits::{StackingContext, WorldPoint};
 
 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
 pub struct FrameId(pub u32);
 
 static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, a: 0.6 };
 
 struct FlattenContext<'a> {
     scene: &'a Scene,
     pipeline_sizes: &'a mut HashMap<PipelineId, LayerSize>,
     builder: &'a mut FrameBuilder,
 }
 
 // TODO: doc
 pub struct Frame {
-    pub layers: LayerMap,
+    pub scroll_tree: ScrollTree,
     pub pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
     pub pipeline_auxiliary_lists: AuxiliaryListsMap,
-    pub root_scroll_layer_id: Option<ScrollLayerId>,
-    pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>,
-    current_scroll_layer_id: Option<ScrollLayerId>,
     id: FrameId,
     debug: bool,
     frame_builder_config: FrameBuilderConfig,
     frame_builder: Option<FrameBuilder>,
 }
 
 trait DisplayListHelpers {
     fn starting_stacking_context<'a>(&'a self) -> Option<(&'a StackingContext, &'a ClipRegion)>;
@@ -202,309 +190,57 @@ impl<'a> Iterator for DisplayListTravers
     }
 }
 
 impl Frame {
     pub fn new(debug: bool, config: FrameBuilderConfig) -> Frame {
         Frame {
             pipeline_epoch_map: HashMap::with_hasher(Default::default()),
             pipeline_auxiliary_lists: HashMap::with_hasher(Default::default()),
-            layers: HashMap::with_hasher(Default::default()),
-            root_scroll_layer_id: None,
-            pending_scroll_offsets: HashMap::new(),
-            current_scroll_layer_id: None,
+            scroll_tree: ScrollTree::new(),
             id: FrameId(0),
             debug: debug,
             frame_builder: None,
             frame_builder_config: config,
         }
     }
 
-    pub fn reset(&mut self)
-                 -> HashMap<ScrollLayerId, ScrollingState, BuildHasherDefault<FnvHasher>> {
+    pub fn reset(&mut self) -> ScrollStates {
         self.pipeline_epoch_map.clear();
 
-        // Free any render targets from last frame.
-        // TODO: This should really re-use existing targets here...
-        let mut old_layer_scrolling_states = HashMap::with_hasher(Default::default());
-        for (layer_id, old_layer) in &mut self.layers.drain() {
-            old_layer_scrolling_states.insert(layer_id, old_layer.scrolling);
-        }
-
         // Advance to the next frame.
         self.id.0 += 1;
 
-        old_layer_scrolling_states
-    }
-
-    pub fn get_scroll_layer(&self, cursor: &WorldPoint, scroll_layer_id: ScrollLayerId)
-                            -> Option<ScrollLayerId> {
-        self.layers.get(&scroll_layer_id).and_then(|layer| {
-            for child_layer_id in layer.children.iter().rev() {
-                if let Some(layer_id) = self.get_scroll_layer(cursor, *child_layer_id) {
-                    return Some(layer_id);
-                }
-            }
-
-            match scroll_layer_id.info {
-                ScrollLayerInfo::Fixed => {
-                    None
-                }
-                ScrollLayerInfo::Scrollable(..) => {
-                    let inv = layer.world_viewport_transform.inverse().unwrap();
-                    let z0 = -10000.0;
-                    let z1 =  10000.0;
-
-                    let p0 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z0, 1.0));
-                    let p0 = Point3D::new(p0.x / p0.w,
-                                          p0.y / p0.w,
-                                          p0.z / p0.w);
-                    let p1 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z1, 1.0));
-                    let p1 = Point3D::new(p1.x / p1.w,
-                                          p1.y / p1.w,
-                                          p1.z / p1.w);
-
-                    let is_unscrollable = layer.content_size.width <= layer.local_viewport_rect.size.width &&
-                        layer.content_size.height <= layer.local_viewport_rect.size.height;
-                    if is_unscrollable {
-                        None
-                    } else {
-                        let result = ray_intersects_rect(p0, p1, layer.local_viewport_rect.to_untyped());
-                        if result {
-                            Some(scroll_layer_id)
-                        } else {
-                            None
-                        }
-                    }
-                }
-            }
-        })
+        self.scroll_tree.drain()
     }
 
     pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
-        let mut result = vec![];
-        for (scroll_layer_id, scroll_layer) in &self.layers {
-            match scroll_layer_id.info {
-                ScrollLayerInfo::Scrollable(_, servo_scroll_root_id) => {
-                    result.push(ScrollLayerState {
-                        pipeline_id: scroll_layer.pipeline_id,
-                        scroll_root_id: servo_scroll_root_id,
-                        scroll_offset: scroll_layer.scrolling.offset,
-                    })
-                }
-                ScrollLayerInfo::Fixed => {}
-            }
-        }
-        result
+        self.scroll_tree.get_scroll_layer_state()
     }
 
     /// Returns true if any layers actually changed position or false otherwise.
     pub fn scroll_layers(&mut self,
                          origin: LayerPoint,
                          pipeline_id: PipelineId,
                          scroll_root_id: ServoScrollRootId)
                           -> bool {
-        let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));
-
-        let mut scrolled_a_layer = false;
-        let mut found_layer = false;
-        for (layer_id, layer) in self.layers.iter_mut() {
-            if layer_id.pipeline_id != pipeline_id {
-                continue;
-            }
-
-            match layer_id.info {
-                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
-                ScrollLayerInfo::Fixed => continue,
-                _ => {}
-            }
-
-            found_layer = true;
-            scrolled_a_layer |= layer.set_scroll_origin(&origin);
-        }
-
-        if !found_layer {
-            self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin);
-        }
-
-        scrolled_a_layer
+        self.scroll_tree.scroll_layers(origin, pipeline_id, scroll_root_id)
     }
 
     /// Returns true if any layers actually changed position or false otherwise.
     pub fn scroll(&mut self,
                   scroll_location: ScrollLocation,
                   cursor: WorldPoint,
                   phase: ScrollEventPhase)
                   -> bool {
-        let root_scroll_layer_id = match self.root_scroll_layer_id {
-            Some(root_scroll_layer_id) => root_scroll_layer_id,
-            None => return false,
-        };
-
-        let scroll_layer_id = match (
-            phase,
-            self.get_scroll_layer(&cursor, root_scroll_layer_id),
-            self.current_scroll_layer_id) {
-            (ScrollEventPhase::Start, Some(scroll_layer_id), _) => {
-                self.current_scroll_layer_id = Some(scroll_layer_id);
-                scroll_layer_id
-            },
-            (ScrollEventPhase::Start, None, _) => return false,
-            (_, _, Some(scroll_layer_id)) => scroll_layer_id,
-            (_, _, None) => return false,
-        };
-
-        let non_root_overscroll = if scroll_layer_id != root_scroll_layer_id {
-            // true if the current layer is overscrolling,
-            // and it is not the root scroll layer.
-            let child_layer = self.layers.get(&scroll_layer_id).unwrap();
-            let overscroll_amount = child_layer.overscroll_amount();
-            overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0
-        } else {
-            false
-        };
-
-        let switch_layer = match phase {
-            ScrollEventPhase::Start => {
-                // if this is a new gesture, we do not switch layer,
-                // however we do save the state of non_root_overscroll,
-                // for use in the subsequent Move phase.
-                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
-                current_layer.scrolling.should_handoff_scroll = non_root_overscroll;
-                false
-            },
-            ScrollEventPhase::Move(_) => {
-                // Switch layer if movement originated in a new gesture,
-                // from a non root layer in overscroll.
-                let current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
-                current_layer.scrolling.should_handoff_scroll && non_root_overscroll
-            },
-            ScrollEventPhase::End => {
-                // clean-up when gesture ends.
-                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
-                current_layer.scrolling.should_handoff_scroll = false;
-                false
-            },
-        };
-
-        let scroll_root_id = match (switch_layer, scroll_layer_id.info, root_scroll_layer_id.info) {
-            (true, _, ScrollLayerInfo::Scrollable(_, scroll_root_id)) |
-            (true, ScrollLayerInfo::Scrollable(_, scroll_root_id), ScrollLayerInfo::Fixed) |
-            (false, ScrollLayerInfo::Scrollable(_, scroll_root_id), _) => scroll_root_id,
-            (_, ScrollLayerInfo::Fixed, _) => unreachable!("Tried to scroll a fixed position layer."),
-        };
-
-        let mut scrolled_a_layer = false;
-        for (layer_id, layer) in self.layers.iter_mut() {
-            if layer_id.pipeline_id != scroll_layer_id.pipeline_id {
-                continue;
-            }
-
-            match layer_id.info {
-                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
-                ScrollLayerInfo::Fixed => continue,
-                _ => {}
-            }
-
-            if layer.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
-                continue;
-            }
-
-            let mut delta = match scroll_location {
-                ScrollLocation::Delta(delta) => delta,
-                ScrollLocation::Start => {
-                    if layer.scrolling.offset.y.round() >= 0.0 {
-                        // Nothing to do on this layer.
-                        continue;
-                    }
-
-                    layer.scrolling.offset.y = 0.0;
-                    scrolled_a_layer = true;
-                    continue;
-                },
-                ScrollLocation::End => {
-                    let end_pos = layer.local_viewport_rect.size.height
-                                  - layer.content_size.height;
-
-                    if layer.scrolling.offset.y.round() <= end_pos {
-                        // Nothing to do on this layer.
-                        continue;
-                    }
-
-                    layer.scrolling.offset.y = end_pos;
-                    scrolled_a_layer = true;
-                    continue;
-                }
-            };
-
-            let overscroll_amount = layer.overscroll_amount();
-            let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
-                                                   overscroll_amount.height != 0.0);
-            if overscrolling {
-                if overscroll_amount.width != 0.0 {
-                    delta.x /= overscroll_amount.width.abs()
-                }
-                if overscroll_amount.height != 0.0 {
-                    delta.y /= overscroll_amount.height.abs()
-                }
-            }
-
-            let is_unscrollable =
-                layer.content_size.width <= layer.local_viewport_rect.size.width &&
-                layer.content_size.height <= layer.local_viewport_rect.size.height;
-
-            let original_layer_scroll_offset = layer.scrolling.offset;
-
-            if layer.content_size.width > layer.local_viewport_rect.size.width {
-                layer.scrolling.offset.x = layer.scrolling.offset.x + delta.x;
-                if is_unscrollable || !CAN_OVERSCROLL {
-                    layer.scrolling.offset.x = layer.scrolling.offset.x.min(0.0);
-                    layer.scrolling.offset.x =
-                        layer.scrolling.offset.x.max(-layer.content_size.width +
-                                                     layer.local_viewport_rect.size.width);
-                }
-            }
-
-            if layer.content_size.height > layer.local_viewport_rect.size.height {
-                layer.scrolling.offset.y = layer.scrolling.offset.y + delta.y;
-                if is_unscrollable || !CAN_OVERSCROLL {
-                    layer.scrolling.offset.y = layer.scrolling.offset.y.min(0.0);
-                    layer.scrolling.offset.y =
-                        layer.scrolling.offset.y.max(-layer.content_size.height +
-                                                     layer.local_viewport_rect.size.height);
-                }
-            }
-
-            if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
-                layer.scrolling.started_bouncing_back = false
-            } else if overscrolling &&
-                    ((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
-                layer.scrolling.started_bouncing_back = true;
-                layer.scrolling.bouncing_back = true
-            }
-
-            layer.scrolling.offset.x = layer.scrolling.offset.x.round();
-            layer.scrolling.offset.y = layer.scrolling.offset.y.round();
-
-            if CAN_OVERSCROLL {
-                layer.stretch_overscroll_spring();
-            }
-
-            scrolled_a_layer = scrolled_a_layer ||
-                layer.scrolling.offset != original_layer_scroll_offset ||
-                layer.scrolling.started_bouncing_back;
-        }
-
-        scrolled_a_layer
+        self.scroll_tree.scroll(scroll_location, cursor, phase,)
     }
 
     pub fn tick_scrolling_bounce_animations(&mut self) {
-        for (_, layer) in &mut self.layers {
-            layer.tick_scrolling_bounce_animation()
-        }
+        self.scroll_tree.tick_scrolling_bounce_animations();
     }
 
     pub fn create(&mut self,
                   scene: &Scene,
                   pipeline_sizes: &mut HashMap<PipelineId, LayerSize>) {
         let root_pipeline_id = match scene.root_pipeline_id {
             Some(root_pipeline_id) => root_pipeline_id,
             None => return,
@@ -516,42 +252,41 @@ impl Frame {
         };
 
         let display_list = scene.display_lists.get(&root_pipeline_id);
         let display_list = match display_list {
             Some(display_list) => display_list,
             None => return,
         };
 
-        let old_layer_scrolling_states = self.reset();
+        let old_scrolling_states = self.reset();
         self.pipeline_auxiliary_lists = scene.pipeline_auxiliary_lists.clone();
 
         self.pipeline_epoch_map.insert(root_pipeline_id, root_pipeline.epoch);
 
         let (root_stacking_context, root_clip) = match display_list.starting_stacking_context() {
             Some(some) => some,
             None => {
                 warn!("Pipeline display list does not start with a stacking context.");
                 return;
             }
         };
 
+        // Insert global position: fixed elements layer
+        debug_assert!(self.scroll_tree.layers.is_empty());
         let root_scroll_layer_id = ScrollLayerId::root(root_pipeline_id);
-        self.root_scroll_layer_id = Some(root_scroll_layer_id);
-
-        // Insert global position: fixed elements layer
-        debug_assert!(self.layers.is_empty());
         let root_fixed_layer_id = ScrollLayerId::create_fixed(root_pipeline_id);
         let root_viewport = LayerRect::new(LayerPoint::zero(), root_pipeline.viewport_size);
         let layer = Layer::new(&root_viewport,
                                root_clip.main.size,
                                &LayerToScrollTransform::identity(),
                                root_pipeline_id);
-        self.layers.insert(root_fixed_layer_id, layer.clone());
-        self.layers.insert(root_scroll_layer_id, layer);
+        self.scroll_tree.add_layer(layer.clone(), root_fixed_layer_id, None);
+        self.scroll_tree.add_layer(layer, root_scroll_layer_id, None);
+        self.scroll_tree.root_scroll_layer_id = Some(root_scroll_layer_id);
 
         let background_color = root_pipeline.background_color.and_then(|color| {
             if color.a > 0.0 {
                 Some(color)
             } else {
                 None
             }
         });
@@ -576,39 +311,17 @@ impl Frame {
                                           root_scroll_layer_id,
                                           LayerToScrollTransform::identity(),
                                           0,
                                           &root_stacking_context,
                                           root_clip);
         }
 
         self.frame_builder = Some(frame_builder);
-
-        // TODO(gw): These are all independent - can be run through thread pool if it shows up
-        // in the profile!
-        for (scroll_layer_id, layer) in &mut self.layers {
-            let scrolling_state = match old_layer_scrolling_states.get(&scroll_layer_id) {
-                Some(old_scrolling_state) => *old_scrolling_state,
-                None => ScrollingState::new(),
-            };
-
-            layer.finalize(&scrolling_state);
-
-            let scroll_root_id = match scroll_layer_id.info {
-                ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
-                _ => continue,
-            };
-
-
-            let pipeline_id = scroll_layer_id.pipeline_id;
-            if let Some(pending_offset) =
-                self.pending_scroll_offsets.get_mut(&(pipeline_id, scroll_root_id)) {
-                layer.set_scroll_origin(pending_offset);
-            }
-        }
+        self.scroll_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
     }
 
     fn flatten_scroll_layer<'a>(&mut self,
                                 traversal: &mut DisplayListTraversal<'a>,
                                 pipeline_id: PipelineId,
                                 context: &mut FlattenContext,
                                 current_fixed_layer_id: ScrollLayerId,
                                 mut current_scroll_layer_id: ScrollLayerId,
@@ -618,27 +331,18 @@ impl Frame {
                                 content_size: &LayerSize,
                                 new_scroll_layer_id: ScrollLayerId) {
         // Avoid doing unnecessary work for empty stacking contexts.
         if traversal.current_stacking_context_empty() {
             traversal.skip_current_stacking_context();
             return;
         }
 
-        debug_assert!(!self.layers.contains_key(&new_scroll_layer_id));
-
         let layer = Layer::new(&clip, *content_size, &layer_relative_transform, pipeline_id);
-        debug_assert!(current_scroll_layer_id != new_scroll_layer_id);
-
-        self.layers
-            .get_mut(&current_scroll_layer_id)
-            .unwrap()
-            .add_child(new_scroll_layer_id);
-
-        self.layers.insert(new_scroll_layer_id, layer);
+        self.scroll_tree.add_layer(layer, new_scroll_layer_id, Some(current_scroll_layer_id));
         current_scroll_layer_id = new_scroll_layer_id;
 
         let layer_rect = LayerRect::new(LayerPoint::zero(),
                                         LayerSize::new(content_size.width + clip.origin.x,
                                                        content_size.height + clip.origin.y));
         context.builder.push_layer(layer_rect,
                                    &ClipRegion::simple(&layer_rect),
                                    LayerToScrollTransform::identity(),
@@ -741,21 +445,21 @@ impl Frame {
                            context,
                            current_fixed_layer_id,
                            current_scroll_layer_id,
                            transform,
                            level);
 
         if level == 0 && self.frame_builder_config.enable_scrollbars {
             let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
-            context.builder.add_solid_rectangle(&scrollbar_rect,
-                                                &ClipRegion::simple(&scrollbar_rect),
-                                                &DEFAULT_SCROLLBAR_COLOR,
-                                                PrimitiveFlags::Scrollbar(self.root_scroll_layer_id.unwrap(),
-                                                                          4.0));
+            context.builder.add_solid_rectangle(
+                &scrollbar_rect,
+                &ClipRegion::simple(&scrollbar_rect),
+                &DEFAULT_SCROLLBAR_COLOR,
+                PrimitiveFlags::Scrollbar(self.scroll_tree.root_scroll_layer_id.unwrap(), 4.0));
         }
 
         context.builder.pop_layer();
     }
 
     fn flatten_iframe<'a>(&mut self,
                           pipeline_id: PipelineId,
                           bounds: &LayerRect,
@@ -792,19 +496,18 @@ impl Frame {
 
         let iframe_fixed_layer_id = ScrollLayerId::create_fixed(pipeline_id);
         let iframe_scroll_layer_id = ScrollLayerId::root(pipeline_id);
 
         let layer = Layer::new(iframe_rect,
                                iframe_clip.main.size,
                                &transform,
                                pipeline_id);
-        self.layers.insert(iframe_fixed_layer_id, layer.clone());
-        self.layers.insert(iframe_scroll_layer_id, layer);
-        self.layers.get_mut(&current_scroll_layer_id).unwrap().add_child(iframe_scroll_layer_id);
+        self.scroll_tree.add_layer(layer.clone(), iframe_fixed_layer_id, None);
+        self.scroll_tree.add_layer(layer, iframe_scroll_layer_id, Some(current_scroll_layer_id));
 
         let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
 
         self.flatten_stacking_context(&mut traversal,
                                       pipeline_id,
                                       context,
                                       iframe_fixed_layer_id,
                                       iframe_scroll_layer_id,
@@ -924,113 +627,34 @@ impl Frame {
         }
     }
 
     pub fn build(&mut self,
                  resource_cache: &mut ResourceCache,
                  auxiliary_lists_map: &AuxiliaryListsMap,
                  device_pixel_ratio: f32)
                  -> RendererFrame {
-        self.update_layer_transforms();
+        self.scroll_tree.update_all_layer_transforms();
         let frame = self.build_frame(resource_cache,
                                      auxiliary_lists_map,
                                      device_pixel_ratio);
         resource_cache.expire_old_resources(self.id);
         frame
     }
 
-    fn update_layer_transform(&mut self,
-                              layer_id: ScrollLayerId,
-                              parent_world_transform: &ScrollToWorldTransform,
-                              parent_viewport_rect: &ScrollLayerRect) {
-        // TODO(gw): This is an ugly borrow check workaround to clone these.
-        //           Restructure this to avoid the clones!
-        let (layer_transform_for_children, viewport_rect, layer_children) = {
-            match self.layers.get_mut(&layer_id) {
-                Some(layer) => {
-                    let inv_transform = layer.local_transform.inverse().unwrap();
-                    let parent_viewport_rect_in_local_space = inv_transform.transform_rect(parent_viewport_rect)
-                                                                           .translate(&-layer.scrolling.offset);
-                    let local_viewport_rect = layer.local_viewport_rect
-                                                   .translate(&-layer.scrolling.offset);
-                    let viewport_rect = parent_viewport_rect_in_local_space.intersection(&local_viewport_rect)
-                                                                           .unwrap_or(LayerRect::zero());
-
-                    layer.combined_local_viewport_rect = viewport_rect;
-                    layer.world_viewport_transform = parent_world_transform.pre_mul(&layer.local_transform);
-                    layer.world_content_transform = layer.world_viewport_transform
-                                                         .pre_translated(layer.scrolling.offset.x,
-                                                                         layer.scrolling.offset.y,
-                                                                         0.0);
-
-                    (layer.world_content_transform.with_source::<ScrollLayerPixel>(),
-                     viewport_rect,
-                     layer.children.clone())
-                }
-                None => return,
-            }
-        };
-
-        for child_layer_id in layer_children {
-            self.update_layer_transform(child_layer_id,
-                                        &layer_transform_for_children,
-                                        &as_scroll_parent_rect(&viewport_rect));
-        }
-    }
-
-    fn update_layer_transforms(&mut self) {
-        if let Some(root_scroll_layer_id) = self.root_scroll_layer_id {
-            let root_viewport = self.layers[&root_scroll_layer_id].local_viewport_rect;
-
-            self.update_layer_transform(root_scroll_layer_id,
-                                        &ScrollToWorldTransform::identity(),
-                                        &as_scroll_parent_rect(&root_viewport));
-
-            // Update any fixed layers
-            let mut fixed_layers = Vec::new();
-            for (layer_id, _) in &self.layers {
-                match layer_id.info {
-                    ScrollLayerInfo::Scrollable(..) => {}
-                    ScrollLayerInfo::Fixed => {
-                        fixed_layers.push(*layer_id);
-                    }
-                }
-            }
-
-            for layer_id in fixed_layers {
-                self.update_layer_transform(layer_id,
-                                            &ScrollToWorldTransform::identity(),
-                                            &as_scroll_parent_rect(&root_viewport));
-            }
-        }
-    }
-
     fn build_frame(&mut self,
                    resource_cache: &mut ResourceCache,
                    auxiliary_lists_map: &AuxiliaryListsMap,
                    device_pixel_ratio: f32) -> RendererFrame {
         let mut frame_builder = self.frame_builder.take();
         let frame = frame_builder.as_mut().map(|builder|
             builder.build(resource_cache,
                           self.id,
-                          &self.layers,
+                          &self.scroll_tree,
                           auxiliary_lists_map,
                           device_pixel_ratio)
         );
         self.frame_builder = frame_builder;
 
-        let layers_bouncing_back = self.collect_layers_bouncing_back();
-        RendererFrame::new(self.pipeline_epoch_map.clone(),
-                           layers_bouncing_back,
-                           frame)
-    }
-
-    fn collect_layers_bouncing_back(&self)
-                                    -> HashSet<ScrollLayerId, BuildHasherDefault<FnvHasher>> {
-        let mut layers_bouncing_back = HashSet::with_hasher(Default::default());
-        for (scroll_layer_id, layer) in &self.layers {
-            if layer.scrolling.bouncing_back {
-                layers_bouncing_back.insert(*scroll_layer_id);
-            }
-        }
-        layers_bouncing_back
+        let layers_bouncing_back = self.scroll_tree.collect_layers_bouncing_back();
+        RendererFrame::new(self.pipeline_epoch_map.clone(), layers_bouncing_back, frame)
     }
 }
--- a/gfx/webrender/src/layer.rs
+++ b/gfx/webrender/src/layer.rs
@@ -1,16 +1,26 @@
 /* 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::Point3D;
+use geometry::ray_intersects_rect;
 use spring::{DAMPING, STIFFNESS, Spring};
-use webrender_traits::{PipelineId, ScrollLayerId};
-use webrender_traits::{LayerRect, LayerPoint, LayerSize};
-use webrender_traits::{LayerToScrollTransform, LayerToWorldTransform};
+use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
+use webrender_traits::{LayerToWorldTransform, PipelineId, ScrollEventPhase, ScrollLayerId};
+use webrender_traits::{ScrollLayerRect, ScrollLocation, ScrollToWorldTransform, WorldPoint};
+use webrender_traits::{WorldPoint4D};
+
+#[cfg(target_os = "macos")]
+const CAN_OVERSCROLL: bool = true;
+
+#[cfg(not(target_os = "macos"))]
+const CAN_OVERSCROLL: bool = false;
+
 
 /// Contains scrolling and transform information stacking contexts.
 #[derive(Clone)]
 pub struct Layer {
     /// Manages scrolling offset, overscroll state etc.
     pub scrolling: ScrollingState,
 
     /// Size of the content inside the scroll region (in logical pixels)
@@ -61,70 +71,194 @@ impl Layer {
         self.children.push(child);
     }
 
     pub fn finalize(&mut self, scrolling: &ScrollingState) {
         self.scrolling = *scrolling;
     }
 
     pub fn overscroll_amount(&self) -> LayerSize {
+        let scrollable_width = self.scrollable_width();
         let overscroll_x = if self.scrolling.offset.x > 0.0 {
             -self.scrolling.offset.x
-        } else if self.scrolling.offset.x < self.local_viewport_rect.size.width - self.content_size.width {
-            self.local_viewport_rect.size.width - self.content_size.width - self.scrolling.offset.x
+        } else if self.scrolling.offset.x < -scrollable_width {
+            -scrollable_width - self.scrolling.offset.x
         } else {
             0.0
         };
 
+        let scrollable_height = self.scrollable_height();
         let overscroll_y = if self.scrolling.offset.y > 0.0 {
             -self.scrolling.offset.y
-        } else if self.scrolling.offset.y < self.local_viewport_rect.size.height -
-                self.content_size.height {
-            self.local_viewport_rect.size.height - self.content_size.height - self.scrolling.offset.y
+        } else if self.scrolling.offset.y < -scrollable_height {
+            -scrollable_height - self.scrolling.offset.y
         } else {
             0.0
         };
 
         LayerSize::new(overscroll_x, overscroll_y)
     }
 
     pub fn set_scroll_origin(&mut self, origin: &LayerPoint) -> bool {
-        if self.content_size.width <= self.local_viewport_rect.size.width &&
-           self.content_size.height <= self.local_viewport_rect.size.height {
+        let scrollable_height = self.scrollable_height();
+        let scrollable_width = self.scrollable_width();
+        if scrollable_height <= 0. && scrollable_width <= 0. {
             return false;
         }
 
-        let new_offset = LayerPoint::new(
-            (-origin.x).max(-self.content_size.width + self.local_viewport_rect.size.width),
-            (-origin.y).max(-self.content_size.height + self.local_viewport_rect.size.height));
-        let new_offset = LayerPoint::new(new_offset.x.min(0.0).round(), new_offset.y.min(0.0).round());
+        let new_offset = LayerPoint::new((-origin.x).max(-scrollable_width).min(0.0).round(),
+                                         (-origin.y).max(-scrollable_height).min(0.0).round());
         if new_offset == self.scrolling.offset {
             return false;
         }
 
         self.scrolling.offset = new_offset;
         self.scrolling.bouncing_back = false;
         self.scrolling.started_bouncing_back = false;
         return true;
     }
 
+    pub fn update_transform(&mut self,
+                            parent_world_transform: &ScrollToWorldTransform,
+                            parent_viewport_rect: &ScrollLayerRect) {
+        let inv_transform = self.local_transform.inverse().unwrap();
+        let parent_viewport_rect_in_local_space = inv_transform.transform_rect(parent_viewport_rect)
+                                                               .translate(&-self.scrolling.offset);
+        let local_viewport_rect = self.local_viewport_rect.translate(&-self.scrolling.offset);
+        let viewport_rect = parent_viewport_rect_in_local_space.intersection(&local_viewport_rect)
+                                                               .unwrap_or(LayerRect::zero());
+
+        self.combined_local_viewport_rect = viewport_rect;
+        self.world_viewport_transform = parent_world_transform.pre_mul(&self.local_transform);
+        self.world_content_transform = self.world_viewport_transform
+                                                     .pre_translated(self.scrolling.offset.x,
+                                                                     self.scrolling.offset.y,
+                                                                     0.0);
+    }
+
+    pub fn scrollable_height(&self) -> f32 {
+        self.content_size.height - self.local_viewport_rect.size.height
+    }
+
+    pub fn scrollable_width(&self) -> f32 {
+        self.content_size.width - self.local_viewport_rect.size.width
+    }
+
+    pub fn scroll(&mut self, scroll_location: ScrollLocation, phase: ScrollEventPhase) -> bool {
+        if self.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
+            return false;
+        }
+
+        let mut delta = match scroll_location {
+            ScrollLocation::Delta(delta) => delta,
+            ScrollLocation::Start => {
+                if self.scrolling.offset.y.round() >= 0.0 {
+                    // Nothing to do on this layer.
+                    return false;
+                }
+
+                self.scrolling.offset.y = 0.0;
+                return true;
+            },
+            ScrollLocation::End => {
+                let end_pos = self.local_viewport_rect.size.height - self.content_size.height;
+
+                if self.scrolling.offset.y.round() <= end_pos {
+                    // Nothing to do on this layer.
+                    return false;
+                }
+
+                self.scrolling.offset.y = end_pos;
+                return true;
+            }
+        };
+
+        let overscroll_amount = self.overscroll_amount();
+        let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
+                                               overscroll_amount.height != 0.0);
+        if overscrolling {
+            if overscroll_amount.width != 0.0 {
+                delta.x /= overscroll_amount.width.abs()
+            }
+            if overscroll_amount.height != 0.0 {
+                delta.y /= overscroll_amount.height.abs()
+            }
+        }
+
+        let scrollable_width = self.scrollable_width();
+        let scrollable_height = self.scrollable_height();
+        let is_unscrollable = scrollable_width <= 0. && scrollable_height <= 0.;
+        let original_layer_scroll_offset = self.scrolling.offset;
+
+        if scrollable_width > 0. {
+            self.scrolling.offset.x = self.scrolling.offset.x + delta.x;
+            if is_unscrollable || !CAN_OVERSCROLL {
+                self.scrolling.offset.x =
+                    self.scrolling.offset.x.min(0.0).max(-scrollable_width).round();
+            }
+        }
+
+        if scrollable_height > 0. {
+            self.scrolling.offset.y = self.scrolling.offset.y + delta.y;
+            if is_unscrollable || !CAN_OVERSCROLL {
+                self.scrolling.offset.y =
+                    self.scrolling.offset.y.min(0.0).max(-scrollable_height).round();
+            }
+        }
+
+        if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
+            self.scrolling.started_bouncing_back = false
+        } else if overscrolling &&
+                ((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
+            self.scrolling.started_bouncing_back = true;
+            self.scrolling.bouncing_back = true
+        }
+
+        if CAN_OVERSCROLL {
+            self.stretch_overscroll_spring();
+        }
+
+        self.scrolling.offset != original_layer_scroll_offset ||
+            self.scrolling.started_bouncing_back
+    }
+
     pub fn stretch_overscroll_spring(&mut self) {
         let overscroll_amount = self.overscroll_amount();
         self.scrolling.spring.coords(self.scrolling.offset,
                                      self.scrolling.offset,
                                      self.scrolling.offset + overscroll_amount);
     }
 
     pub fn tick_scrolling_bounce_animation(&mut self) {
         let finished = self.scrolling.spring.animate();
         self.scrolling.offset = self.scrolling.spring.current();
         if finished {
             self.scrolling.bouncing_back = false
         }
     }
+
+    pub fn ray_intersects_layer(&self, cursor: &WorldPoint) -> bool {
+        let inv = self.world_viewport_transform.inverse().unwrap();
+        let z0 = -10000.0;
+        let z1 =  10000.0;
+
+        let p0 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z0, 1.0));
+        let p0 = Point3D::new(p0.x / p0.w,
+                              p0.y / p0.w,
+                              p0.z / p0.w);
+        let p1 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z1, 1.0));
+        let p1 = Point3D::new(p1.x / p1.w,
+                              p1.y / p1.w,
+                              p1.z / p1.w);
+
+        if self.scrollable_width() <= 0. && self.scrollable_height() <= 0. {
+            return false;
+        }
+        ray_intersects_rect(p0, p1, self.local_viewport_rect.to_untyped())
+    }
 }
 
 #[derive(Copy, Clone)]
 pub struct ScrollingState {
     pub offset: LayerPoint,
     pub spring: Spring,
     pub started_bouncing_back: bool,
     pub bouncing_back: bool,
--- a/gfx/webrender/src/lib.rs
+++ b/gfx/webrender/src/lib.rs
@@ -62,16 +62,17 @@ mod internal_types;
 mod layer;
 mod mask_cache;
 mod prim_store;
 mod profiler;
 mod record;
 mod render_backend;
 mod resource_cache;
 mod scene;
+mod scroll_tree;
 mod spring;
 mod texture_cache;
 mod tiling;
 mod util;
 
 mod shader_source {
     include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
 }
--- a/gfx/webrender/src/platform/macos/font.rs
+++ b/gfx/webrender/src/platform/macos/font.rs
@@ -10,17 +10,17 @@ use core_graphics::context::{CGContext, 
 use core_graphics::data_provider::CGDataProvider;
 use core_graphics::font::{CGFont, CGGlyph};
 use core_graphics::geometry::{CGPoint, CGSize, CGRect};
 use core_text::font::CTFont;
 use core_text::font_descriptor::kCTFontDefaultOrientation;
 use core_text;
 use std::collections::HashMap;
 use std::collections::hash_map::Entry;
-use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
+use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions};
 
 pub type NativeFontHandle = CGFont;
 
 pub struct FontContext {
     cg_fonts: HashMap<FontKey, CGFont>,
     ct_fonts: HashMap<(FontKey, Au), CTFont>,
 }
 
@@ -173,16 +173,17 @@ impl FontContext {
             }
             println!("");
         }
     }
 
     pub fn rasterize_glyph(&mut self,
                            font_key: FontKey,
                            size: Au,
+                           color: ColorU,
                            character: u32,
                            render_mode: FontRenderMode) -> Option<RasterizedGlyph> {
         match self.get_ct_font(font_key, size) {
             Some(ref ct_font) => {
                 let glyph = character as CGGlyph;
                 let metrics = get_glyph_metrics(ct_font, glyph);
                 if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
                     return Some(RasterizedGlyph::blank())
--- a/gfx/webrender/src/platform/unix/font.rs
+++ b/gfx/webrender/src/platform/unix/font.rs
@@ -1,14 +1,14 @@
 /* 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 app_units::Au;
-use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions, NativeFontHandle};
+use webrender_traits::{FontKey, ColorU, FontRenderMode, GlyphDimensions, NativeFontHandle};
 
 use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode};
 use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
 use freetype::freetype::{FT_Library, FT_Set_Char_Size};
 use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
 use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
 use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
 
@@ -128,115 +128,123 @@ impl FontContext {
                 })
             }
         })
     }
 
     pub fn rasterize_glyph(&mut self,
                            font_key: FontKey,
                            size: Au,
+                           color: ColorU,
                            character: u32,
                            render_mode: FontRenderMode) -> Option<RasterizedGlyph> {
         let mut glyph = None;
 
         if let Some(slot) = self.load_glyph(font_key,
                                             size,
                                             character) {
             let render_mode = match render_mode {
                 FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
                 FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
                 FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
             };
 
-            unsafe {
-                let result = FT_Render_Glyph(slot, render_mode);
+            let result = unsafe { FT_Render_Glyph(slot, render_mode) };
 
-                if result.succeeded() {
-                    let bitmap = &(*slot).bitmap;
+            if result.succeeded() {
+                let bitmap = unsafe { &(*slot).bitmap };
 
-                    let metrics = &(*slot).metrics;
-                    let mut glyph_width = (metrics.width >> 6) as i32;
-                    let glyph_height = (metrics.height >> 6) as i32;
-                    let mut final_buffer = Vec::with_capacity(glyph_width as usize *
-                                                              glyph_height as usize *
-                                                              4);
+                let metrics = unsafe { &(*slot).metrics };
+                let mut glyph_width = (metrics.width >> 6) as i32;
+                let glyph_height = (metrics.height >> 6) as i32;
+                let mut final_buffer = Vec::with_capacity(glyph_width as usize *
+                                                          glyph_height as usize *
+                                                          4);
+
+                if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_MONO as u8 {
+                    // This is not exactly efficient... but it's only used by the
+                    // reftest pass when we have AA disabled on glyphs.
+                    let offset_x = unsafe { (metrics.horiBearingX >> 6) as i32 - (*slot).bitmap_left };
+                    let offset_y = unsafe { (metrics.horiBearingY >> 6) as i32 - (*slot).bitmap_top };
 
-                    if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_MONO as u8 {
-                        // This is not exactly efficient... but it's only used by the
-                        // reftest pass when we have AA disabled on glyphs.
-                        let offset_x = (metrics.horiBearingX >> 6) as i32 - (*slot).bitmap_left;
-                        let offset_y = (metrics.horiBearingY >> 6) as i32 - (*slot).bitmap_top;
+                    // Due to AA being disabled, the bitmap produced for mono
+                    // glyphs is often smaller than the reported glyph dimensions.
+                    // To account for this, place the rendered glyph within the
+                    // box of the glyph dimensions, filling in invalid pixels with
+                    // zero alpha.
+                    for iy in 0..glyph_height {
+                        let y = iy - offset_y;
+                        for ix in 0..glyph_width {
+                            let x = ix + offset_x;
+                            let valid_byte = x >= 0 &&
+                                y >= 0 &&
+                                x < bitmap.width as i32 &&
+                                y < bitmap.rows as i32;
+                            let byte_value = if valid_byte {
+                                let byte_index = (y * bitmap.pitch as i32) + (x >> 3);
 
-                        // Due to AA being disabled, the bitmap produced for mono
-                        // glyphs is often smaller than the reported glyph dimensions.
-                        // To account for this, place the rendered glyph within the
-                        // box of the glyph dimensions, filling in invalid pixels with
-                        // zero alpha.
-                        for iy in 0..glyph_height {
-                            let y = iy - offset_y;
-                            for ix in 0..glyph_width {
-                                let x = ix + offset_x;
-                                let valid_byte = x >= 0 &&
-                                                 y >= 0 &&
-                                                 x < bitmap.width as i32 &&
-                                                 y < bitmap.rows as i32;
-                                let byte_value = if valid_byte {
-                                    let byte_index = (y * bitmap.pitch as i32) + (x >> 3);
+                                unsafe {
                                     let bit_index = x & 7;
                                     let byte_ptr = bitmap.buffer.offset(byte_index as isize);
                                     let bit = (*byte_ptr & (0x80 >> bit_index)) != 0;
                                     if bit {
                                         0xff
                                     } else {
                                         0
                                     }
-                                } else {
-                                    0
-                                };
+                                }
+                            } else {
+                                0
+                            };
 
-                                final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte_value ]);
-                            }
+                            final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte_value ]);
                         }
-                    } else if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_GRAY as u8 {
-                        // We can assume that the reported glyph dimensions exactly
-                        // match the rasterized bitmap for normal alpha coverage glyphs.
+                    }
+                } else if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_GRAY as u8 {
+                    // We can assume that the reported glyph dimensions exactly
+                    // match the rasterized bitmap for normal alpha coverage glyphs.
 
-                        let buffer = slice::from_raw_parts(
+                    let buffer = unsafe {
+                        slice::from_raw_parts(
                             bitmap.buffer,
                             (bitmap.width * bitmap.rows) as usize
-                        );
+                        )
+                    };
 
-                        // Convert to RGBA.
-                        for &byte in buffer.iter() {
-                            final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte ]);
-                        }
-                    } else if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_LCD as u8 {
-                        // Extra subpixel on each side of the glyph.
-                        glyph_width += 2;
+                    // Convert to RGBA.
+                    for &byte in buffer.iter() {
+                        final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte ]);
+                    }
+                } else if bitmap.pixel_mode == FT_Pixel_Mode::FT_PIXEL_MODE_LCD as u8 {
+                    // Extra subpixel on each side of the glyph.
+                    glyph_width += 2;
 
-                        for y in 0..bitmap.rows {
-                            for x in 0..(bitmap.width / 3) {
-                                let index = (y as i32 * bitmap.pitch) + (x as i32 * 3);
+                    for y in 0..bitmap.rows {
+                        for x in 0..(bitmap.width / 3) {
+                            let index = (y as i32 * bitmap.pitch) + (x as i32 * 3);
+
+                            unsafe {
                                 let ptr = bitmap.buffer.offset(index as isize);
                                 let b = *ptr;
                                 let g = *(ptr.offset(1));
                                 let r = *(ptr.offset(2));
-                                final_buffer.extend_from_slice(&[ r, g, b, 0xff ]);
+
+                                final_buffer.extend_from_slice(&[r, g, b, 0xff]);
                             }
                         }
-                    } else {
-                        panic!("Unexpected render mode: {}!", bitmap.pixel_mode);
                     }
+                } else {
+                    panic!("Unexpected render mode: {}!", bitmap.pixel_mode);
+                }
 
-                    glyph = Some(RasterizedGlyph {
-                        width: glyph_width as u32,
-                        height: glyph_height as u32,
-                        bytes: final_buffer,
-                    });
-                }
+                glyph = Some(RasterizedGlyph {
+                    width: glyph_width as u32,
+                    height: glyph_height as u32,
+                    bytes: final_buffer,
+                });
             }
         }
 
         glyph
     }
 }
 
 impl Drop for FontContext {
--- a/gfx/webrender/src/platform/windows/font.rs
+++ b/gfx/webrender/src/platform/windows/font.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 app_units::Au;
 use std::collections::HashMap;
-use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
+use webrender_traits::{FontKey, ColorU, FontRenderMode, GlyphDimensions};
 
 use dwrote;
 
 lazy_static! {
     static ref DEFAULT_FONT_DESCRIPTOR: dwrote::FontDescriptor = dwrote::FontDescriptor {
         family_name: "Arial".to_owned(),
         weight: dwrote::FontWeight::Regular,
         stretch: dwrote::FontStretch::Normal,
@@ -177,15 +177,16 @@ impl FontContext {
         let (maybe_dims, _) =
             self.get_glyph_dimensions_and_maybe_rasterize(font_key, size, glyph, None);
         maybe_dims
     }
 
     pub fn rasterize_glyph(&mut self,
                            font_key: FontKey,
                            size: Au,
+                           color: ColorU,
                            glyph: u32,
                            render_mode: FontRenderMode) -> Option<RasterizedGlyph> {
         let (_, maybe_glyph) =
             self.get_glyph_dimensions_and_maybe_rasterize(font_key, size, glyph, Some(render_mode));
         maybe_glyph
     }
 }
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -732,19 +732,19 @@ impl PrimitiveStore {
                 PrimitiveKind::Gradient |
                 PrimitiveKind::RadialGradient=> {}
                 PrimitiveKind::TextRun => {
                     let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
                     let font_size_dp = text.logical_font_size.scale_by(device_pixel_ratio);
 
                     let dest_rects = self.gpu_resource_rects.get_slice_mut(text.resource_address,
                                                                            text.glyph_range.length);
-
                     let texture_id = resource_cache.get_glyphs(text.font_key,
                                                                font_size_dp,
+                                                               text.color,
                                                                &text.glyph_indices,
                                                                text.render_mode, |index, uv0, uv1| {
                         let dest_rect = &mut dest_rects[index];
                         dest_rect.uv0 = uv0;
                         dest_rect.uv1 = uv1;
                     });
 
                     text.color_texture_id = texture_id;
@@ -928,16 +928,17 @@ impl PrimitiveStore {
 
                     debug_assert!(metadata.gpu_data_count == text.glyph_range.length as i32);
                     debug_assert!(text.glyph_indices.is_empty());
                     let src_glyphs = auxiliary_lists.glyph_instances(&text.glyph_range);
                     let dest_glyphs = self.gpu_data16.get_slice_mut(metadata.gpu_data_address,
                                                                     text.glyph_range.length);
                     let mut glyph_key = GlyphKey::new(text.font_key,
                                                       font_size_dp,
+                                                      text.color,
                                                       src_glyphs[0].index);
                     let mut local_rect = LayerRect::zero();
                     let mut actual_glyph_count = 0;
 
                     for src in src_glyphs {
                         glyph_key.index = src.index;
 
                         let dimensions = match resource_cache.get_glyph_dimensions(&glyph_key) {
@@ -993,33 +994,34 @@ impl PrimitiveStore {
 
                     metadata.gpu_data_count = actual_glyph_count as i32;
                     metadata.render_task = render_task;
                     self.gpu_geometry.get_mut(GpuStoreAddress(prim_index.0 as i32)).local_rect = local_rect;
                 }
 
                 resource_cache.request_glyphs(text.font_key,
                                               font_size_dp,
+                                              text.color,
                                               &text.glyph_indices,
                                               text.render_mode);
             }
             PrimitiveKind::Image => {
                 let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0];
 
                 prim_needs_resolve = true;
                 match image_cpu.kind {
                     ImagePrimitiveKind::Image(image_key, image_rendering, tile_spacing) => {
                         resource_cache.request_image(image_key, image_rendering);
 
                         // TODO(gw): This doesn't actually need to be calculated each frame.
                         // It's cheap enough that it's not worth introducing a cache for images
                         // right now, but if we introduce a cache for images for some other
                         // reason then we might as well cache this with it.
                         let image_properties = resource_cache.get_image_properties(image_key);
-                        metadata.is_opaque = image_properties.is_opaque &&
+                        metadata.is_opaque = image_properties.descriptor.is_opaque &&
                                              tile_spacing.width == 0.0 &&
                                              tile_spacing.height == 0.0;
                     }
                     ImagePrimitiveKind::WebGL(..) => {}
                 }
             }
             PrimitiveKind::YuvImage => {
                 let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -120,33 +120,24 @@ impl RenderBackend {
                         ApiMsg::GetGlyphDimensions(glyph_keys, tx) => {
                             let mut glyph_dimensions = Vec::with_capacity(glyph_keys.len());
                             for glyph_key in &glyph_keys {
                                 let glyph_dim = self.resource_cache.get_glyph_dimensions(glyph_key);
                                 glyph_dimensions.push(glyph_dim);
                             };
                             tx.send(glyph_dimensions).unwrap();
                         }
-                        ApiMsg::AddImage(id, width, height, stride, format, data) => {
+                        ApiMsg::AddImage(id, descriptor, data) => {
                             if let ImageData::Raw(ref bytes) = data {
                                 profile_counters.image_templates.inc(bytes.len());
                             }
-                            self.resource_cache.add_image_template(id,
-                                                                   width,
-                                                                   height,
-                                                                   stride,
-                                                                   format,
-                                                                   data);
+                            self.resource_cache.add_image_template(id, descriptor, data);
                         }
-                        ApiMsg::UpdateImage(id, width, height, format, bytes) => {
-                            self.resource_cache.update_image_template(id,
-                                                                      width,
-                                                                      height,
-                                                                      format,
-                                                                      bytes);
+                        ApiMsg::UpdateImage(id, descriptor, bytes) => {
+                            self.resource_cache.update_image_template(id, descriptor, bytes);
                         }
                         ApiMsg::DeleteImage(id) => {
                             self.resource_cache.delete_image_template(id);
                         }
                         ApiMsg::CloneApi(sender) => {
                             let result = self.next_namespace_id;
 
                             let IdNamespace(id_namespace) = self.next_namespace_id;
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -34,16 +34,17 @@ use std::thread;
 use texture_cache::TextureCache;
 use tiling::{Frame, FrameBuilderConfig, PrimitiveBatch, PrimitiveBatchData};
 use tiling::{BlurCommand, CacheClipInstance, PrimitiveInstance, RenderTarget};
 use time::precise_time_ns;
 use util::TransformedRectKind;
 use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
 use webrender_traits::{ExternalImageId, ImageFormat, RenderApiSender, RendererKind};
 use webrender_traits::{DeviceIntRect, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
+use webrender_traits::ImageDescriptor;
 use webrender_traits::channel;
 use webrender_traits::VRCompositorHandler;
 
 pub const VERTEX_TEXTURE_POOL: usize = 5;
 pub const MAX_VERTEX_TEXTURE_WIDTH: usize = 1024;
 
 const GPU_TAG_CACHE_BOX_SHADOW: GpuProfileTag = GpuProfileTag { label: "C_BoxShadow", color: debug_colors::BLACK };
 const GPU_TAG_CACHE_CLIP: GpuProfileTag = GpuProfileTag { label: "C_Clip", color: debug_colors::PURPLE };
@@ -546,29 +547,35 @@ impl Renderer {
         ];
         let mask_pixels: Vec<u8> = vec![
             0xff, 0xff,
             0xff, 0xff,
         ];
         // TODO: Ensure that the white texture can never get evicted when the cache supports LRU eviction!
         let white_image_id = texture_cache.new_item_id();
         texture_cache.insert(white_image_id,
-                             2,
-                             2,
-                             None,
-                             ImageFormat::RGBA8,
+                             ImageDescriptor {
+                                width: 2,
+                                height: 2,
+                                stride: None,
+                                format: ImageFormat::RGBA8,
+                                is_opaque: false,
+                             },
                              TextureFilter::Linear,
                              Arc::new(white_pixels));
 
         let dummy_mask_image_id = texture_cache.new_item_id();
         texture_cache.insert(dummy_mask_image_id,
-                             2,
-                             2,
-                             None,
-                             ImageFormat::A8,
+                             ImageDescriptor {
+                                width: 2,
+                                height: 2,
+                                stride: None,
+                                format: ImageFormat::A8,
+                                is_opaque: false,
+                             },
                              TextureFilter::Linear,
                              Arc::new(mask_pixels));
 
         let debug_renderer = DebugRenderer::new(&mut device);
 
         let vertex_textures = [
             VertexTextures::new(&mut device),
             VertexTextures::new(&mut device),
@@ -729,16 +736,22 @@ impl Renderer {
         *handler_arc = Some(creator);
     }
 
     /// Returns the Epoch of the current frame in a pipeline.
     pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch> {
         self.pipeline_epoch_map.get(&pipeline_id).cloned()
     }
 
+    /// Returns a HashMap containing the pipeline ids that have been received by the renderer and
+    /// their respective epochs since the last time the method was called.
+    pub fn flush_rendered_epochs(&mut self) -> HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>> {
+        return mem::replace(&mut self.pipeline_epoch_map, HashMap::with_hasher(Default::default()));
+    }
+
     /// Processes the result queue.
     ///
     /// Should be called before `render()`, as texture cache updates are done here.
     pub fn update(&mut self) {
         // Pull any pending results and return the most recent.
         while let Ok(msg) = self.result_rx.try_recv() {
             match msg {
                 ResultMsg::NewFrame(frame, texture_update_list, external_image_update_list, profile_counters) => {
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -16,32 +16,32 @@ use std::hash::BuildHasherDefault;
 use std::hash::Hash;
 use std::mem;
 use std::sync::{Arc, Barrier};
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::thread;
 use texture_cache::{TextureCache, TextureCacheItemId};
 use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, ImageRendering};
 use webrender_traits::{FontRenderMode, ImageData, GlyphDimensions, WebGLContextId};
-use webrender_traits::{DevicePoint, DeviceIntSize};
+use webrender_traits::{DevicePoint, DeviceIntSize, ImageDescriptor, ColorF};
 use webrender_traits::ExternalImageId;
 use threadpool::ThreadPool;
 
 thread_local!(pub static FONT_CONTEXT: RefCell<FontContext> = RefCell::new(FontContext::new()));
 
 type GlyphCache = ResourceClassCache<RenderedGlyphKey, Option<TextureCacheItemId>>;
 
 /// Message sent from the resource cache to the glyph cache thread.
 enum GlyphCacheMsg {
     /// Begin the frame - pass ownership of the glyph cache to the thread.
     BeginFrame(FrameId, GlyphCache),
     /// Add a new font.
     AddFont(FontKey, FontTemplate),
     /// Request glyphs for a text run.
-    RequestGlyphs(FontKey, Au, Vec<u32>, FontRenderMode),
+    RequestGlyphs(FontKey, Au, ColorF, Vec<u32>, FontRenderMode),
     /// Finished requesting glyphs. Reply with new glyphs.
     EndFrame,
 }
 
 /// Results send from glyph cache thread back to main resource cache.
 enum GlyphCacheResultMsg {
     /// Return the glyph cache, and a list of newly rasterized glyphs.
     EndFrame(GlyphCache, Vec<GlyphRasterJob>),
@@ -66,49 +66,42 @@ pub struct CacheItem {
 pub struct RenderedGlyphKey {
     pub key: GlyphKey,
     pub render_mode: FontRenderMode,
 }
 
 impl RenderedGlyphKey {
     pub fn new(font_key: FontKey,
                size: Au,
+               color: ColorF,
                index: u32,
                render_mode: FontRenderMode) -> RenderedGlyphKey {
         RenderedGlyphKey {
-            key: GlyphKey::new(font_key, size, index),
+            key: GlyphKey::new(font_key, size, color, index),
             render_mode: render_mode,
         }
     }
 }
 
 pub struct ImageProperties {
-    pub format: ImageFormat,
-    pub is_opaque: bool,
+    pub descriptor: ImageDescriptor,
     pub external_id: Option<ExternalImageId>,
-    pub width: u32,
-    pub height: u32,
-    pub stride: Option<u32>,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq)]
 enum State {
     Idle,
     AddResources,
     QueryResources,
 }
 
 struct ImageResource {
     data: ImageData,
-    width: u32,
-    height: u32,
-    stride: Option<u32>,
-    format: ImageFormat,
+    descriptor: ImageDescriptor,
     epoch: Epoch,
-    is_opaque: bool,
 }
 
 struct CachedImageInfo {
     texture_cache_id: TextureCacheItemId,
     epoch: Epoch,
 }
 
 pub struct ResourceClassCache<K,V> {
@@ -240,43 +233,30 @@ impl ResourceCache {
         self.glyph_cache_tx
             .send(GlyphCacheMsg::AddFont(font_key, template.clone()))
             .unwrap();
         self.font_templates.insert(font_key, template);
     }
 
     pub fn add_image_template(&mut self,
                               image_key: ImageKey,
-                              width: u32,
-                              height: u32,
-                              stride: Option<u32>,
-                              format: ImageFormat,
+                              descriptor: ImageDescriptor,
                               data: ImageData) {
-        let is_opaque = match data {
-            ImageData::Raw(ref bytes) => is_image_opaque(format, bytes),
-            ImageData::External(..) => false,           // TODO: Allow providing this through API.
-        };
         let resource = ImageResource {
-            is_opaque: is_opaque,
-            width: width,
-            height: height,
-            stride: stride,
-            format: format,
+            descriptor: descriptor,
             data: data,
             epoch: Epoch(0),
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn update_image_template(&mut self,
                                  image_key: ImageKey,
-                                 width: u32,
-                                 height: u32,
-                                 format: ImageFormat,
+                                 descriptor: ImageDescriptor,
                                  bytes: Vec<u8>) {
         let next_epoch = match self.image_templates.get(&image_key) {
             Some(image) => {
                 // This image should not be an external image.
                 match image.data {
                     ImageData::External(id) => {
                         panic!("Update an external image with buffer, id={} image_key={:?}", id.0, image_key);
                     },
@@ -287,21 +267,17 @@ impl ResourceCache {
                 Epoch(current_epoch + 1)
             }
             None => {
                 Epoch(0)
             }
         };
 
         let resource = ImageResource {
-            is_opaque: is_image_opaque(format, &bytes),
-            width: width,
-            height: height,
-            stride: None,
-            format: format,
+            descriptor: descriptor,
             data: ImageData::new(bytes),
             epoch: next_epoch,
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn delete_image_template(&mut self, image_key: ImageKey) {
@@ -345,49 +321,53 @@ impl ResourceCache {
             key: key,
             rendering: rendering,
         });
     }
 
     pub fn request_glyphs(&mut self,
                           key: FontKey,
                           size: Au,
+                          color: ColorF,
                           glyph_indices: &[u32],
                           render_mode: FontRenderMode) {
         debug_assert!(self.state == State::AddResources);
         let render_mode = self.get_glyph_render_mode(render_mode);
         // Immediately request that the glyph cache thread start
         // rasterizing glyphs from this request if they aren't
         // already cached.
         let msg = GlyphCacheMsg::RequestGlyphs(key,
                                                size,
+                                               color,
                                                glyph_indices.to_vec(),
                                                render_mode);
         self.glyph_cache_tx.send(msg).unwrap();
     }
 
     pub fn pending_updates(&mut self) -> TextureUpdateList {
         self.texture_cache.pending_updates()
     }
 
     pub fn pending_external_image_updates(&mut self) -> ExternalImageUpdateList {
         mem::replace(&mut self.pending_external_image_update_list, ExternalImageUpdateList::new())
     }
 
     pub fn get_glyphs<F>(&self,
                          font_key: FontKey,
                          size: Au,
+                         color: ColorF,
                          glyph_indices: &[u32],
                          render_mode: FontRenderMode,
                          mut f: F) -> SourceTexture where F: FnMut(usize, DevicePoint, DevicePoint) {
         debug_assert!(self.state == State::QueryResources);
         let cache = self.cached_glyphs.as_ref().unwrap();
         let render_mode = self.get_glyph_render_mode(render_mode);
         let mut glyph_key = RenderedGlyphKey::new(font_key,
                                                   size,
+                                                  color,
                                                   0,
                                                   render_mode);
         let mut texture_id = None;
         for (loop_index, glyph_index) in glyph_indices.iter().enumerate() {
             glyph_key.key.index = *glyph_index;
             let image_id = cache.get(&glyph_key, self.current_frame_id);
             let cache_item = image_id.map(|image_id| self.texture_cache.get(image_id));
             if let Some(cache_item) = cache_item {
@@ -458,22 +438,18 @@ impl ResourceCache {
         let image_template = &self.image_templates[&image_key];
 
         let external_id = match image_template.data {
             ImageData::External(id) => Some(id),
             ImageData::Raw(..) => None,
         };
 
         ImageProperties {
-            format: image_template.format,
-            is_opaque: image_template.is_opaque,
+            descriptor: image_template.descriptor,
             external_id: external_id,
-            width: image_template.width,
-            height: image_template.height,
-            stride: image_template.stride,
         }
     }
 
     #[inline]
     pub fn get_webgl_texture(&self, context_id: &WebGLContextId) -> CacheItem {
         let webgl_texture = &self.webgl_textures[context_id];
         CacheItem {
             texture_id: webgl_texture.id,
@@ -518,20 +494,23 @@ impl ResourceCache {
             match result {
                 GlyphCacheResultMsg::EndFrame(mut cache, glyph_jobs) => {
                     // Add any newly rasterized glyphs to the texture cache.
                     for job in glyph_jobs {
                         let image_id = job.result.and_then(|glyph| {
                             if glyph.width > 0 && glyph.height > 0 {
                                 let image_id = self.texture_cache.new_item_id();
                                 self.texture_cache.insert(image_id,
-                                                          glyph.width,
-                                                          glyph.height,
-                                                          None,
-                                                          ImageFormat::RGBA8,
+                                                          ImageDescriptor {
+                                                              width: glyph.width,
+                                                              height: glyph.height,
+                                                              stride: None,
+                                                              format: ImageFormat::RGBA8,
+                                                              is_opaque: false,
+                                                          },
                                                           TextureFilter::Linear,
                                                           Arc::new(glyph.bytes));
                                 Some(image_id)
                             } else {
                                 None
                             }
                         });
 
@@ -553,20 +532,17 @@ impl ResourceCache {
                 ImageData::Raw(ref bytes) => {
                     match cached_images.entry(request.clone(), self.current_frame_id) {
                         Occupied(entry) => {
                             let image_id = entry.get().texture_cache_id;
 
                             if entry.get().epoch != image_template.epoch {
                                 // TODO: Can we avoid the clone of the bytes here?
                                 self.texture_cache.update(image_id,
-                                                          image_template.width,
-                                                          image_template.height,
-                                                          image_template.stride,
-                                                          image_template.format,
+                                                          image_template.descriptor,
                                                           bytes.clone());
 
                                 // Update the cached epoch
                                 *entry.into_mut() = CachedImageInfo {
                                     texture_cache_id: image_id,
                                     epoch: image_template.epoch,
                                 };
                             }
@@ -576,20 +552,17 @@ impl ResourceCache {
 
                             let filter = match request.rendering {
                                 ImageRendering::Pixelated => TextureFilter::Nearest,
                                 ImageRendering::Auto | ImageRendering::CrispEdges => TextureFilter::Linear,
                             };
 
                             // TODO: Can we avoid the clone of the bytes here?
                             self.texture_cache.insert(image_id,
-                                                      image_template.width,
-                                                      image_template.height,
-                                                      image_template.stride,
-                                                      image_template.format,
+                                                      image_template.descriptor,
                                                       filter,
                                                       bytes.clone());
 
                             entry.insert(CachedImageInfo {
                                 texture_cache_id: image_id,
                                 epoch: image_template.epoch,
                             });
                         }
@@ -630,40 +603,16 @@ impl Resource for Option<TextureCacheIte
 }
 
 impl Resource for CachedImageInfo {
     fn texture_cache_item_id(&self) -> Option<TextureCacheItemId> {
         Some(self.texture_cache_id)
     }
 }
 
-// TODO(gw): If this ever shows up in profiles, consider calculating
-// this lazily on demand, possibly via the resource cache thread.
-// It can probably be made a lot faster with SIMD too!
-// This assumes that A8 textures are never opaque, since they are
-// typically used for alpha masks. We could revisit that if it
-// ever becomes an issue in real world usage.
-fn is_image_opaque(format: ImageFormat, bytes: &[u8]) -> bool {
-    match format {
-        ImageFormat::RGBA8 => {
-            let mut is_opaque = true;
-            for i in 0..(bytes.len() / 4) {
-                if bytes[i * 4 + 3] != 255 {
-                    is_opaque = false;
-                    break;
-                }
-            }
-            is_opaque
-        }
-        ImageFormat::RGB8 => true,
-        ImageFormat::A8 => false,
-        ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
-    }
-}
-
 fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResultMsg>) {
     // Used for messages from resource cache -> glyph cache thread.
     let (msg_tx, msg_rx) = channel();
     // Used for returning results from glyph cache thread -> resource cache.
     let (result_tx, result_rx) = channel();
     // Used for rasterizer worker threads to send glyphs -> glyph cache thread.
     let (glyph_tx, glyph_rx) = channel();
 
@@ -714,39 +663,41 @@ fn spawn_glyph_cache_thread() -> (Sender
                                     }
                                 }
                             });
 
                             barrier.wait();
                         });
                     }
                 }
-                GlyphCacheMsg::RequestGlyphs(key, size, indices, render_mode) => {
+                GlyphCacheMsg::RequestGlyphs(key, size, color, indices, render_mode) => {
                     // Request some glyphs for a text run.
                     // For any glyph that isn't currently in the cache,
                     // immeediately push a job to the worker thread pool
                     // to start rasterizing this glyph now!
                     let glyph_cache = glyph_cache.as_mut().unwrap();
 
                     for glyph_index in indices {
                         let glyph_key = RenderedGlyphKey::new(key,
                                                               size,
+                                                              color,
                                                               glyph_index,
                                                               render_mode);
 
                         glyph_cache.mark_as_needed(&glyph_key, current_frame_id);
                         if !glyph_cache.contains_key(&glyph_key) &&
                            !pending_glyphs.contains(&glyph_key) {
                             let glyph_tx = glyph_tx.clone();
                             pending_glyphs.insert(glyph_key.clone());
                             thread_pool.execute(move || {
                                 FONT_CONTEXT.with(move |font_context| {
                                     let mut font_context = font_context.borrow_mut();
                                     let result = font_context.rasterize_glyph(glyph_key.key.font_key,
                                                                               glyph_key.key.size,
+                                                                              glyph_key.key.color,
                                                                               glyph_key.key.index,
                                                                               render_mode);
                                     glyph_tx.send((glyph_key, result)).unwrap();
                                 });
                             });
                         }
                     }
                 }
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/src/scroll_tree.rs
@@ -0,0 +1,309 @@
+/* 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 fnv::FnvHasher;
+use layer::{Layer, ScrollingState};
+use std::collections::{HashMap, HashSet};
+use std::hash::BuildHasherDefault;
+use webrender_traits::{LayerPoint, PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerInfo};
+use webrender_traits::{ScrollLayerPixel, ScrollLayerRect, ScrollLayerState, ScrollLocation};
+use webrender_traits::{ScrollToWorldTransform, ServoScrollRootId, WorldPoint};
+use webrender_traits::as_scroll_parent_rect;
+
+pub type ScrollStates = HashMap<ScrollLayerId, ScrollingState, BuildHasherDefault<FnvHasher>>;
+
+pub struct ScrollTree {
+    pub layers: HashMap<ScrollLayerId, Layer, BuildHasherDefault<FnvHasher>>,
+    pub pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>,
+    pub current_scroll_layer_id: Option<ScrollLayerId>,
+    pub root_scroll_layer_id: Option<ScrollLayerId>,
+}
+
+impl ScrollTree {
+    pub fn new() -> ScrollTree {
+        ScrollTree {
+            layers: HashMap::with_hasher(Default::default()),
+            pending_scroll_offsets: HashMap::new(),
+            current_scroll_layer_id: None,
+            root_scroll_layer_id: None,
+        }
+    }
+
+    pub fn collect_layers_bouncing_back(&self)
+                                        -> HashSet<ScrollLayerId, BuildHasherDefault<FnvHasher>> {
+        let mut layers_bouncing_back = HashSet::with_hasher(Default::default());
+        for (scroll_layer_id, layer) in self.layers.iter() {
+            if layer.scrolling.bouncing_back {
+                layers_bouncing_back.insert(*scroll_layer_id);
+            }
+        }
+        layers_bouncing_back
+    }
+
+    pub fn get_scroll_layer(&self,
+                            cursor: &WorldPoint,
+                            scroll_layer_id: ScrollLayerId)
+                            -> Option<ScrollLayerId> {
+        self.layers.get(&scroll_layer_id).and_then(|layer| {
+            for child_layer_id in layer.children.iter().rev() {
+                if let Some(layer_id) = self.get_scroll_layer(cursor, *child_layer_id) {
+                    return Some(layer_id);
+                }
+            }
+
+            if scroll_layer_id.info == ScrollLayerInfo::Fixed {
+                return None;
+            }
+
+            if layer.ray_intersects_layer(cursor) {
+                Some(scroll_layer_id)
+            } else {
+                None
+            }
+        })
+    }
+
+    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
+        let mut result = vec![];
+        for (scroll_layer_id, scroll_layer) in self.layers.iter() {
+            match scroll_layer_id.info {
+                ScrollLayerInfo::Scrollable(_, servo_scroll_root_id) => {
+                    result.push(ScrollLayerState {
+                        pipeline_id: scroll_layer.pipeline_id,
+                        scroll_root_id: servo_scroll_root_id,
+                        scroll_offset: scroll_layer.scrolling.offset,
+                    })
+                }
+                ScrollLayerInfo::Fixed => {}
+            }
+        }
+        result
+    }
+
+    pub fn drain(&mut self) -> ScrollStates {
+        let mut scroll_states = HashMap::with_hasher(Default::default());
+        for (layer_id, old_layer) in &mut self.layers.drain() {
+            scroll_states.insert(layer_id, old_layer.scrolling);
+        }
+        scroll_states
+    }
+
+    pub fn scroll_layers(&mut self,
+                         origin: LayerPoint,
+                         pipeline_id: PipelineId,
+                         scroll_root_id: ServoScrollRootId)
+                         -> bool {
+        let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));
+
+        let mut scrolled_a_layer = false;
+        let mut found_layer = false;
+        for (layer_id, layer) in self.layers.iter_mut() {
+            if layer_id.pipeline_id != pipeline_id {
+                continue;
+            }
+
+            match layer_id.info {
+                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
+                ScrollLayerInfo::Fixed => continue,
+                _ => {}
+            }
+
+            found_layer = true;
+            scrolled_a_layer |= layer.set_scroll_origin(&origin);
+        }
+
+        if !found_layer {
+            self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin);
+        }
+
+        scrolled_a_layer
+    }
+
+    pub fn scroll(&mut self,
+                  scroll_location: ScrollLocation,
+                  cursor: WorldPoint,
+                  phase: ScrollEventPhase)
+                  -> bool {
+        let root_scroll_layer_id = match self.root_scroll_layer_id {
+            Some(root_scroll_layer_id) => root_scroll_layer_id,
+            None => return false,
+        };
+
+        let scroll_layer_id = match (
+            phase,
+            self.get_scroll_layer(&cursor, root_scroll_layer_id),
+            self.current_scroll_layer_id) {
+            (ScrollEventPhase::Start, Some(scroll_layer_id), _) => {
+                self.current_scroll_layer_id = Some(scroll_layer_id);
+                scroll_layer_id
+            },
+            (ScrollEventPhase::Start, None, _) => return false,
+            (_, _, Some(scroll_layer_id)) => scroll_layer_id,
+            (_, _, None) => return false,
+        };
+
+        let non_root_overscroll = if scroll_layer_id != root_scroll_layer_id {
+            // true if the current layer is overscrolling,
+            // and it is not the root scroll layer.
+            let child_layer = self.layers.get(&scroll_layer_id).unwrap();
+            let overscroll_amount = child_layer.overscroll_amount();
+            overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0
+        } else {
+            false
+        };
+
+        let switch_layer = match phase {
+            ScrollEventPhase::Start => {
+                // if this is a new gesture, we do not switch layer,
+                // however we do save the state of non_root_overscroll,
+                // for use in the subsequent Move phase.
+                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
+                current_layer.scrolling.should_handoff_scroll = non_root_overscroll;
+                false
+            },
+            ScrollEventPhase::Move(_) => {
+                // Switch layer if movement originated in a new gesture,
+                // from a non root layer in overscroll.
+                let current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
+                current_layer.scrolling.should_handoff_scroll && non_root_overscroll
+            },
+            ScrollEventPhase::End => {
+                // clean-up when gesture ends.
+                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
+                current_layer.scrolling.should_handoff_scroll = false;
+                false
+            },
+        };
+
+        let scroll_layer_info = if switch_layer {
+            root_scroll_layer_id.info
+        } else {
+            scroll_layer_id.info
+        };
+
+        let scroll_root_id = match scroll_layer_info {
+             ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
+             _ => unreachable!("Tried to scroll a non-scrolling layer."),
+
+        };
+
+        let mut scrolled_a_layer = false;
+        for (layer_id, layer) in self.layers.iter_mut() {
+            if layer_id.pipeline_id != scroll_layer_id.pipeline_id {
+                continue;
+            }
+
+            match layer_id.info {
+                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
+                ScrollLayerInfo::Fixed => continue,
+                _ => {}
+            }
+
+            let scrolled_this_layer = layer.scroll(scroll_location, phase);
+            scrolled_a_layer = scrolled_a_layer || scrolled_this_layer;
+        }
+        scrolled_a_layer
+    }
+
+    pub fn update_all_layer_transforms(&mut self) {
+        let root_scroll_layer_id = self.root_scroll_layer_id;
+        self.update_layer_transforms(root_scroll_layer_id);
+    }
+
+    fn update_layer_transform(&mut self,
+                              layer_id: ScrollLayerId,
+                              parent_world_transform: &ScrollToWorldTransform,
+                              parent_viewport_rect: &ScrollLayerRect) {
+        // TODO(gw): This is an ugly borrow check workaround to clone these.
+        //           Restructure this to avoid the clones!
+        let (layer_transform_for_children, viewport_rect, layer_children) = {
+            match self.layers.get_mut(&layer_id) {
+                Some(layer) => {
+                    layer.update_transform(parent_world_transform, parent_viewport_rect);
+
+                    (layer.world_content_transform.with_source::<ScrollLayerPixel>(),
+                     as_scroll_parent_rect(&layer.combined_local_viewport_rect),
+                     layer.children.clone())
+                }
+                None => return,
+            }
+        };
+
+        for child_layer_id in layer_children {
+            self.update_layer_transform(child_layer_id,
+                                        &layer_transform_for_children,
+                                        &viewport_rect);
+        }
+    }
+
+    pub fn update_layer_transforms(&mut self, root_scroll_layer_id: Option<ScrollLayerId>) {
+        if let Some(root_scroll_layer_id) = root_scroll_layer_id {
+            let root_viewport = self.layers[&root_scroll_layer_id].local_viewport_rect;
+
+            self.update_layer_transform(root_scroll_layer_id,
+                                        &ScrollToWorldTransform::identity(),
+                                        &as_scroll_parent_rect(&root_viewport));
+
+            // Update any fixed layers
+            let mut fixed_layers = Vec::new();
+            for (layer_id, _) in &self.layers {
+                match layer_id.info {
+                    ScrollLayerInfo::Scrollable(..) => {}
+                    ScrollLayerInfo::Fixed => {
+                        fixed_layers.push(*layer_id);
+                    }
+                }
+            }
+
+            for layer_id in fixed_layers {
+                self.update_layer_transform(layer_id,
+                                            &ScrollToWorldTransform::identity(),
+                                            &as_scroll_parent_rect(&root_viewport));
+            }
+        }
+    }
+
+    pub fn tick_scrolling_bounce_animations(&mut self) {
+        for (_, layer) in &mut self.layers {
+            layer.tick_scrolling_bounce_animation()
+        }
+    }
+
+    pub fn finalize_and_apply_pending_scroll_offsets(&mut self, old_states: ScrollStates) {
+        // TODO(gw): These are all independent - can be run through thread pool if it shows up
+        // in the profile!
+        for (scroll_layer_id, layer) in &mut self.layers {
+            let scrolling_state = match old_states.get(&scroll_layer_id) {
+                Some(old_scrolling_state) => *old_scrolling_state,
+                None => ScrollingState::new(),
+            };
+
+            layer.finalize(&scrolling_state);
+
+            let scroll_root_id = match scroll_layer_id.info {
+                ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
+                _ => continue,
+            };
+
+
+            let pipeline_id = scroll_layer_id.pipeline_id;
+            if let Some(pending_offset) =
+                self.pending_scroll_offsets.get_mut(&(pipeline_id, scroll_root_id)) {
+                layer.set_scroll_origin(pending_offset);
+            }
+        }
+
+    }
+
+    pub fn add_layer(&mut self, layer: Layer, id: ScrollLayerId, parent_id: Option<ScrollLayerId>) {
+        debug_assert!(!self.layers.contains_key(&id));
+        self.layers.insert(id, layer);
+
+        if let Some(parent_id) = parent_id {
+            debug_assert!(parent_id != id);
+            self.layers.get_mut(&parent_id).unwrap().add_child(id);
+        }
+    }
+}
+
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -13,16 +13,17 @@ use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
 use std::mem;
 use std::slice::Iter;
 use std::sync::Arc;
 use time;
 use util;
 use webrender_traits::{ImageFormat, DevicePixel, DeviceIntPoint};
 use webrender_traits::{DeviceUintRect, DeviceUintSize, DeviceUintPoint};
+use webrender_traits::ImageDescriptor;
 
 /// The number of bytes we're allowed to use for a texture.
 const MAX_BYTES_PER_TEXTURE: u32 = 1024 * 1024 * 256;  // 256MB
 
 /// The number of RGBA pixels we're allowed to use for a texture.
 const MAX_RGBA_PIXELS_PER_TEXTURE: u32 = MAX_BYTES_PER_TEXTURE / 4;
 
 /// The desired initial size of each texture, in pixels.
@@ -735,64 +736,58 @@ impl TextureCache {
 
             let page = TexturePage::new(texture_id, texture_size);
             page_list.push(page);
         }
     }
 
     pub fn update(&mut self,
                   image_id: TextureCacheItemId,
-                  width: u32,
-                  height: u32,
-                  stride: Option<u32>,
-                  _format: ImageFormat,
+                  descriptor: ImageDescriptor,
                   bytes: Arc<Vec<u8>>) {
         let existing_item = self.items.get(image_id);
 
         // TODO(gw): Handle updates to size/format!
-        debug_assert!(existing_item.requested_rect.size.width == width);
-        debug_assert!(existing_item.requested_rect.size.height == height);
+        debug_assert!(existing_item.requested_rect.size.width == descriptor.width);
+        debug_assert!(existing_item.requested_rect.size.height == descriptor.height);
 
         let op = TextureUpdateOp::Update(existing_item.requested_rect.origin.x,
                                          existing_item.requested_rect.origin.y,
-                                         width,
-                                         height,
+                                         descriptor.width,
+                                         descriptor.height,
                                          bytes,
-                                         stride);
+                                         descriptor.stride);
 
         let update_op = TextureUpdate {
             id: existing_item.texture_id,
             op: op,
         };
 
         self.pending_updates.push(update_op);
     }
 
     pub fn insert(&mut self,
                   image_id: TextureCacheItemId,
-                  width: u32,
-                  height: u32,
-                  stride: Option<u32>,
-                  format: ImageFormat,
+                  descriptor: ImageDescriptor,
                   filter: TextureFilter,
                   bytes: Arc<Vec<u8>>) {
+        let width = descriptor.width;
+        let height = descriptor.height;
+        let format = descriptor.format;
+        let stride = descriptor.stride;
+
         let result = self.allocate(image_id,
                                    width,
                                    height,
                                    format,
                                    filter);
 
         let op = match result.kind {
             AllocationKind::TexturePage => {
-                let bpp = match format {
-                    ImageFormat::A8 => 1,
-                    ImageFormat::RGB8 => 3,
-                    ImageFormat::RGBA8 => 4,
-                    ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
-                };
+                let bpp = format.bytes_per_pixel().unwrap();
 
                 let mut top_row_bytes = Vec::new();
                 let mut bottom_row_bytes = Vec::new();
                 let mut left_column_bytes = Vec::new();
                 let mut right_column_bytes = Vec::new();
 
                 copy_pixels(&bytes, &mut top_row_bytes, 0, 0, 1, width, stride, bpp);
                 copy_pixels(&bytes, &mut top_row_bytes, 0, 0, width, width, stride, bpp);
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -4,30 +4,30 @@
 
 use app_units::Au;
 use batch_builder::BorderSideHelpers;
 use fnv::FnvHasher;
 use frame::FrameId;
 use gpu_store::GpuStoreAddress;
 use internal_types::{ANGLE_FLOAT_TO_FIXED, LowLevelFilterOp, CompositionOp};
 use internal_types::{BatchTextures, CacheTextureId, SourceTexture};
-use layer::Layer;
 use mask_cache::{ClipSource, MaskCacheInfo};
 use prim_store::{PrimitiveGeometry, RectanglePrimitive, PrimitiveContainer};
 use prim_store::{BorderPrimitiveCpu, BorderPrimitiveGpu, BoxShadowPrimitiveGpu};
 use prim_store::{ImagePrimitiveCpu, ImagePrimitiveGpu, YuvImagePrimitiveCpu, YuvImagePrimitiveGpu, ImagePrimitiveKind, };
 use prim_store::{PrimitiveKind, PrimitiveIndex, PrimitiveMetadata, TexelRect};
 use prim_store::{CLIP_DATA_GPU_SIZE, DeferredResolve};
 use prim_store::{GradientPrimitiveCpu, GradientPrimitiveGpu, GradientType};
 use prim_store::{RadialGradientPrimitiveCpu, RadialGradientPrimitiveGpu};
 use prim_store::{PrimitiveCacheKey, TextRunPrimitiveGpu, TextRunPrimitiveCpu};
 use prim_store::{PrimitiveStore, GpuBlock16, GpuBlock32, GpuBlock64, GpuBlock128};
 use profiler::FrameProfileCounters;
 use renderer::BlendMode;
 use resource_cache::ResourceCache;
+use scroll_tree::ScrollTree;
 use std::cmp;
 use std::collections::{HashMap};
 use std::{i32, f32};
 use std::mem;
 use std::hash::{BuildHasherDefault};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::usize;
 use texture_cache::TexturePage;
@@ -44,19 +44,16 @@ use webrender_traits::{LayerToScrollTran
 use webrender_traits::{WorldPoint4D, ScrollLayerPixel, as_scroll_parent_rect};
 
 // Special sentinel value recognized by the shader. It is considered to be
 // a dummy task that doesn't mask out anything.
 const OPAQUE_TASK_INDEX: RenderTaskIndex = RenderTaskIndex(i32::MAX as usize);
 
 const FLOATS_PER_RENDER_TASK_INFO: usize = 12;
 
-pub type LayerMap = HashMap<ScrollLayerId,
-                            Layer,
-                            BuildHasherDefault<FnvHasher>>;
 pub type AuxiliaryListsMap = HashMap<PipelineId,
                                      AuxiliaryLists,
                                      BuildHasherDefault<FnvHasher>>;
 
 trait AlphaBatchHelpers {
     fn get_batch_kind(&self, metadata: &PrimitiveMetadata) -> AlphaBatchKind;
     fn get_color_textures(&self, metadata: &PrimitiveMetadata) -> [SourceTexture; 3];
     fn get_blend_mode(&self, needs_blending: bool, metadata: &PrimitiveMetadata) -> BlendMode;
@@ -2519,17 +2516,17 @@ impl FrameBuilder {
                            clip_region,
                            PrimitiveContainer::YuvImage(prim_cpu, prim_gpu));
     }
 
     /// Compute the contribution (bounding rectangles, and resources) of layers and their
     /// primitives in screen space.
     fn cull_layers(&mut self,
                    screen_rect: &DeviceIntRect,
-                   layer_map: &LayerMap,
+                   scroll_tree: &ScrollTree,
                    auxiliary_lists_map: &AuxiliaryListsMap,
                    x_tile_count: i32,
                    y_tile_count: i32,
                    resource_cache: &mut ResourceCache,
                    profile_counters: &mut FrameProfileCounters,
                    device_pixel_ratio: f32) {
         // Build layer screen rects.
         // TODO(gw): This can be done earlier once update_layer_transforms() is fixed.
@@ -2543,17 +2540,17 @@ impl FrameBuilder {
                 &PrimitiveRunCmd::PushStackingContext(sc_index) => {
                     layer_stack.push(sc_index);
                     let layer = &mut self.layer_store[sc_index.0];
                     let packed_layer = &mut self.packed_layers[sc_index.0];
 
                     layer.xf_rect = None;
                     layer.tile_range = None;
 
-                    let scroll_layer = &layer_map[&layer.scroll_layer_id];
+                    let scroll_layer = &scroll_tree.layers[&layer.scroll_layer_id];
                     packed_layer.transform = scroll_layer.world_content_transform
                                                          .with_source::<ScrollLayerPixel>() // the scroll layer is considered a parent of layer
                                                          .pre_mul(&layer.local_transform);
                     packed_layer.inv_transform = packed_layer.transform.inverse().unwrap();
 
                     if !layer.can_contribute_to_scene() {
                         continue;
                     }
@@ -2665,21 +2662,26 @@ impl FrameBuilder {
 
                                 // Try to create a mask if we may need to.
                                 if !clip_info_stack.is_empty() {
                                     // If the primitive doesn't have a specific clip,
                                     // key the task ID off the stacking context. This means
                                     // that two primitives which are only clipped by the
                                     // stacking context stack can share clip masks during
                                     // render task assignment to targets.
-                                    let mask_key = match prim_clip_info {
-                                        Some(..) => MaskCacheKey::Primitive(prim_index),
-                                        None => MaskCacheKey::StackingContext(*sc_index),
+                                    let (mask_key, mask_rect) = match prim_clip_info {
+                                        Some(..) => {
+                                            (MaskCacheKey::Primitive(prim_index), prim_bounding_rect)
+                                        }
+                                        None => {
+                                            let layer_rect = layer.xf_rect.as_ref().unwrap().bounding_rect;
+                                            (MaskCacheKey::StackingContext(*sc_index), layer_rect)
+                                        }
                                     };
-                                    let mask_opt = RenderTask::new_mask(prim_bounding_rect,
+                                    let mask_opt = RenderTask::new_mask(mask_rect,
                                                                         mask_key,
                                                                         &clip_info_stack,
                                                                         &self.layer_store);
                                     match mask_opt {
                                         MaskResult::Outside => {
                                             // Primitive is completely clipped out.
                                             prim_metadata.clip_task = None;
                                             self.prim_store.cpu_bounding_rects[prim_index.0] = None;
@@ -2861,25 +2863,24 @@ impl FrameBuilder {
                             tile.pop_layer(sc_index);
                         }
                     }
                 }
             }
         }
     }
 
-    fn update_scroll_bars(&mut self,
-                          layer_map: &LayerMap) {
+    fn update_scroll_bars(&mut self, scroll_tree: &ScrollTree) {
         let distance_from_edge = 8.0;
 
         for scrollbar_prim in &self.scrollbar_prims {
             let mut geom = (*self.prim_store.gpu_geometry.get(GpuStoreAddress(scrollbar_prim.prim_index.0 as i32))).clone();
-            let scroll_layer = &layer_map[&scrollbar_prim.scroll_layer_id];
-
-            let scrollable_distance = scroll_layer.content_size.height - scroll_layer.local_viewport_rect.size.height;
+            let scroll_layer = &scroll_tree.layers[&scrollbar_prim.scroll_layer_id];
+
+            let scrollable_distance = scroll_layer.scrollable_height();
 
             if scrollable_distance <= 0.0 {
                 geom.local_clip_rect.size = LayerSize::zero();
                 *self.prim_store.gpu_geometry.get_mut(GpuStoreAddress(scrollbar_prim.prim_index.0 as i32)) = geom;
                 continue;
             }
 
             let f = -scroll_layer.scrolling.offset.y / scrollable_distance;
@@ -2910,17 +2911,17 @@ impl FrameBuilder {
             self.prim_store.set_clip_source(scrollbar_prim.prim_index, clip_source);
             *self.prim_store.gpu_geometry.get_mut(GpuStoreAddress(scrollbar_prim.prim_index.0 as i32)) = geom;
         }
     }
 
     pub fn build(&mut self,
                  resource_cache: &mut ResourceCache,
                  frame_id: FrameId,
-                 layer_map: &LayerMap,
+                 scroll_tree: &ScrollTree,
                  auxiliary_lists_map: &AuxiliaryListsMap,
                  device_pixel_ratio: f32) -> Frame {
         let mut profile_counters = FrameProfileCounters::new();
         profile_counters.total_primitives.set(self.prim_store.prim_count());
 
         resource_cache.begin_frame(frame_id);
 
         let screen_rect = DeviceIntRect::new(
@@ -2943,20 +2944,20 @@ impl FrameBuilder {
         let aligned_max_dimension = (max_dimension + SCREEN_TILE_SIZE - 1) & !(SCREEN_TILE_SIZE-1);
         let cache_size = DeviceUintSize::new(aligned_max_dimension as u32,
                                              aligned_max_dimension as u32);
 
         let mut debug_rects = Vec::new();
 
         let (x_tile_count, y_tile_count, mut screen_tiles) = self.create_screen_tiles(device_pixel_ratio);
 
-        self.update_scroll_bars(layer_map);
+        self.update_scroll_bars(scroll_tree);
 
         self.cull_layers(&screen_rect,
-                         layer_map,
+                         scroll_tree,
                          auxiliary_lists_map,
                          x_tile_count,
                          y_tile_count,
                          resource_cache,
                          &mut profile_counters,
                          device_pixel_ratio);
 
         let mut compiled_screen_tiles = Vec::new();
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/tests/angle_shader_validation.rs
@@ -0,0 +1,85 @@
+extern crate angle;
+#[macro_use]
+extern crate lazy_static;
+extern crate webrender;
+
+use angle::hl::{BuiltInResources, Output, ShaderSpec, ShaderValidator};
+
+include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
+
+
+// from glslang
+const FRAGMENT_SHADER: u32 = 0x8B30;
+const VERTEX_SHADER: u32 = 0x8B31;
+
+
+#[test]
+fn validate_shaders() {
+    angle::hl::initialize().unwrap();
+
+    let shared_src = SHADERS.get("shared").unwrap();
+    let prim_shared_src = SHADERS.get("prim_shared").unwrap();
+    let clip_shared_src = SHADERS.get("clip_shared").unwrap();
+
+    for (filename, file_source) in SHADERS.iter() {
+        let is_prim = filename.starts_with("ps_");
+        let is_clip = filename.starts_with("cs_");
+        let is_vert = filename.ends_with(".vs");
+        let is_frag = filename.ends_with(".fs");
+        if !(is_prim ^ is_clip) || !(is_vert ^ is_frag) {
+            continue;
+        }
+
+
+        let base_filename = filename.splitn(2, '.').next().unwrap();
+        let mut shader_prefix = format!("#version 300 es\n
+            // Base shader: {}\n
+            #define WR_MAX_VERTEX_TEXTURE_WIDTH {}\n",
+            base_filename, webrender::renderer::MAX_VERTEX_TEXTURE_WIDTH);
+
+        if is_vert {
+            shader_prefix.push_str("#define WR_VERTEX_SHADER\n");
+        } else {
+            shader_prefix.push_str("#define WR_FRAGMENT_SHADER\n");
+        }
+
+        let mut build_configs = vec!["#define WR_FEATURE_TRANSFORM\n"];
+        if is_prim {
+            // the transform feature may be disabled for the prim shaders
+            build_configs.push("// WR_FEATURE_TRANSFORM disabled\n");
+        }
+
+        for config_prefix in build_configs {
+            let mut shader_source = String::new();
+            shader_source.push_str(shader_prefix.as_str());
+            shader_source.push_str(config_prefix);
+            shader_source.push_str(shared_src);
+            shader_source.push_str(prim_shared_src);
+            if is_clip {
+                shader_source.push_str(clip_shared_src);
+            }
+            if let Some(optional_src) = SHADERS.get(base_filename) {
+                shader_source.push_str(optional_src);
+            }
+            shader_source.push_str(file_source);
+
+
+            let gl_type = if is_vert { VERTEX_SHADER } else { FRAGMENT_SHADER };
+            let resources = BuiltInResources::default();
+            let validator = ShaderValidator::new(gl_type,
+                                                 ShaderSpec::Gles3,
+                                                 Output::Essl,
+                                                 &resources).unwrap();
+
+            match validator.compile_and_translate(&[&shader_source]) {
+                Ok(_) => {
+                    println!("Shader translated succesfully: {}", filename);
+                },
+                Err(_) => {
+                    panic!("Shader compilation failed: {}\n{}",
+                        filename, validator.info_log());
+                },
+            }
+        }
+    }
+}
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2,17 +2,17 @@ use fnv::FnvHasher;
 use std::collections::HashMap;
 use std::ffi::CString;
 use std::hash::BuildHasherDefault;
 use std::{mem, slice};
 use std::os::raw::{c_void, c_char};
 use gleam::gl;
 use webrender_traits::{BorderSide, BorderStyle, BorderRadius};
 use webrender_traits::{PipelineId, ClipRegion};
-use webrender_traits::{Epoch, ColorF, GlyphInstance};
+use webrender_traits::{Epoch, ColorF, GlyphInstance, ImageDescriptor};
 use webrender_traits::{ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind, MixBlendMode};
 use webrender_traits::{ExternalImageId, RenderApi, FontKey};
 use webrender_traits::{DeviceUintSize, ExternalEvent};
 use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
 use webrender::renderer::{Renderer, RendererOptions};
 use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use std::sync::{Arc, Mutex, Condvar};
 use app_units::Au;
@@ -680,30 +680,30 @@ pub extern fn wr_api_set_root_pipeline(a
 pub extern fn wr_api_add_image(api: &mut RenderApi, width: u32, height: u32, stride: u32, format: ImageFormat, bytes: * const u8, size: usize) -> ImageKey {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
     let stride_option = match stride {
         0 => None,
         _ => Some(stride),
     };
 
-    api.add_image(width, height, stride_option, format, ImageData::new(bytes))
+    api.add_image(ImageDescriptor{width: width, height: height, stride: stride_option, format: format, is_opaque: false}, ImageData::new(bytes))
 }
 
 #[no_mangle]
 pub extern fn wr_api_add_external_image_texture(api: &mut RenderApi, width: u32, height: u32, format: ImageFormat, external_image_id: u64) -> ImageKey {
     assert!( unsafe { is_in_compositor_thread() });
-    api.add_image(width, height, None, format, ImageData::External(ExternalImageId(external_image_id)))
+    api.add_image(ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false}, ImageData::External(ExternalImageId(external_image_id)))
 }
 
 #[no_mangle]
 pub extern fn wr_api_update_image(api: &mut RenderApi, key: ImageKey, width: u32, height: u32, format: ImageFormat, bytes: * const u8, size: usize) {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
-    api.update_image(key, width, height, format, bytes);
+    api.update_image(key, ImageDescriptor{width:width, height:height, stride:None, format:format, is_opaque: false}, bytes);
 }
 #[no_mangle]
 pub extern fn wr_api_delete_image(api: &mut RenderApi, key: ImageKey) {
     assert!( unsafe { is_in_compositor_thread() });
     api.delete_image(key)
 }
 
 #[no_mangle]
--- a/gfx/webrender_traits/src/api.rs
+++ b/gfx/webrender_traits/src/api.rs
@@ -1,18 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use byteorder::{LittleEndian, WriteBytesExt};
 use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
 use std::cell::Cell;
-use {ApiMsg, ColorF, DisplayListBuilder, Epoch};
-use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
+use {ApiMsg, ColorF, DisplayListBuilder, Epoch, ImageDescriptor};
+use {FontKey, IdNamespace, ImageKey, NativeFontHandle, PipelineId};
 use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId};
 use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};
 use {DeviceIntSize, LayoutPoint, LayoutSize, WorldPoint};
 use VRCompositorCommand;
 use ExternalEvent;
 
 impl RenderApiSender {
     pub fn new(api_sender: MsgSender<ApiMsg>,
@@ -85,38 +85,33 @@ impl RenderApi {
     /// Creates an `ImageKey`.
     pub fn alloc_image(&self) -> ImageKey {
         let new_id = self.next_unique_id();
         ImageKey::new(new_id.0, new_id.1)
     }
 
     /// Adds an image and returns the corresponding `ImageKey`.
     pub fn add_image(&self,
-                     width: u32,
-                     height: u32,
-                     stride: Option<u32>,
-                     format: ImageFormat,
+                     descriptor: ImageDescriptor,
                      data: ImageData) -> ImageKey {
         let key = self.alloc_image();
-        let msg = ApiMsg::AddImage(key, width, height, stride, format, data);
+        let msg = ApiMsg::AddImage(key, descriptor, data);
         self.api_sender.send(msg).unwrap();
         key
     }
 
     /// Updates a specific image.
     ///
     /// Currently doesn't support changing dimensions or format by updating.
     // TODO: Support changing dimensions (and format) during image update?
     pub fn update_image(&self,
                         key: ImageKey,
-                        width: u32,
-                        height: u32,
-                        format: ImageFormat,
+                        descriptor: ImageDescriptor,
                         bytes: Vec<u8>) {
-        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
+        let msg = ApiMsg::UpdateImage(key, descriptor, bytes);
         self.api_sender.send(msg).unwrap();
     }
 
     /// Deletes the specific image.
     pub fn delete_image(&self, key: ImageKey) {
         let msg = ApiMsg::DeleteImage(key);
         self.api_sender.send(msg).unwrap();
     }
--- a/gfx/webrender_traits/src/types.rs
+++ b/gfx/webrender_traits/src/types.rs
@@ -23,19 +23,19 @@ pub enum RendererKind {
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
     AddRawFont(FontKey, Vec<u8>),
     AddNativeFont(FontKey, NativeFontHandle),
     /// Gets the glyph dimensions
     GetGlyphDimensions(Vec<GlyphKey>, MsgSender<Vec<Option<GlyphDimensions>>>),
     /// Adds an image from the resource cache.
-    AddImage(ImageKey, u32, u32, Option<u32>, ImageFormat, ImageData),
+    AddImage(ImageKey, ImageDescriptor, ImageData),
     /// Updates the the resource cache with the new image data.
-    UpdateImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
+    UpdateImage(ImageKey, ImageDescriptor, Vec<u8>),
     /// Drops an image from the resource cache.
     DeleteImage(ImageKey),
     CloneApi(MsgSender<IdNamespace>),
     /// Supplies a new frame to WebRender.
     ///
     /// After receiving this message, WebRender will read the display list, followed by the
     /// auxiliary lists, from the payload channel.
     SetRootDisplayList(Option<ColorF>,
@@ -186,16 +186,74 @@ pub struct BuiltDisplayListDescriptor {
 pub struct ColorF {
     pub r: f32,
     pub g: f32,
     pub b: f32,
     pub a: f32,
 }
 known_heap_size!(0, ColorF);
 
+#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, PartialEq, PartialOrd, Ord, Serialize)]
+pub struct ColorU {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+    pub a: u8,
+}
+
+impl From<ColorF> for ColorU {
+    fn from(color: ColorF) -> ColorU {
+        ColorU {
+            r: ColorU::round_to_int(color.r),
+            g: ColorU::round_to_int(color.g),
+            b: ColorU::round_to_int(color.b),
+            a: ColorU::round_to_int(color.a),
+        }
+    }
+}
+
+impl Into<ColorF> for ColorU {
+    fn into(self) -> ColorF {
+        ColorF {
+            r: self.r as f32 / 255.0,
+            g: self.g as f32 / 255.0,
+            b: self.b as f32 / 255.0,
+            a: self.a as f32 / 255.0,
+        }
+    }
+}
+
+impl ColorU {
+    fn round_to_int(x: f32) -> u8 {
+        debug_assert!((0.0 <= x) && (x <= 1.0));
+        let f = (255.0 * x) + 0.5;
+        let val = f.floor();
+        debug_assert!(val <= 255.0);
+        val as u8
+    }
+
+    pub fn new(r: u8, g: u8, b: u8, a: u8) -> ColorU {
+        ColorU {
+            r: r,
+            g: g,
+            b: b,
+            a: a,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
+pub struct ImageDescriptor {
+    pub format: ImageFormat,
+    pub width: u32,
+    pub height: u32,
+    pub stride: Option<u32>,
+    pub is_opaque: bool,
+}
+
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ImageMask {
     pub image: ImageKey,
     pub rect: LayoutRect,
     pub repeat: bool,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@@ -258,25 +316,28 @@ pub struct GlyphKey {
     pub font_key: FontKey,
     // The font size is in *device* pixels, not logical pixels.
     // It is stored as an Au since we need sub-pixel sizes, but
     // can't store as a f32 due to use of this type as a hash key.
     // TODO(gw): Perhaps consider having LogicalAu and DeviceAu
     //           or something similar to that.
     pub size: Au,
     pub index: u32,
+    pub color: ColorU,
 }
 
 impl GlyphKey {
     pub fn new(font_key: FontKey,
                size: Au,
+               color: ColorF,
                index: u32) -> GlyphKey {
         GlyphKey {
             font_key: font_key,
             size: size,
+            color: ColorU::from(color),
             index: index,
         }
     }
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum FragmentType {
     FragmentBody,
@@ -353,16 +414,28 @@ pub struct YuvImageDisplayItem {
 pub enum ImageFormat {
     Invalid,
     A8,
     RGB8,
     RGBA8,
     RGBAF32,
 }
 
+impl ImageFormat {
+    pub fn bytes_per_pixel(self) -> Option<u32> {
+        match self {
+            ImageFormat::A8 => Some(1),
+            ImageFormat::RGB8 => Some(3),
+            ImageFormat::RGBA8 => Some(4),
+            ImageFormat::RGBAF32 => Some(16),
+            ImageFormat::Invalid => None,
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum YuvColorSpace {
     Rec601 = 1, // The values must match the ones in prim_shared.glsl
     Rec709 = 2,
 }
 
 /// An arbitrary identifier for an external image provided by the
 /// application. It must be a unique identifier for each external
--- a/third_party/rust/dwrote/.cargo-checksum.json
+++ b/third_party/rust/dwrote/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"172610b244a5ee8a8e2f1f045058b8abf9291d84bb76bf8779d2fd420419c2d6","Cargo.toml":"2abdbe33c0b8b7167287225ef902e43548a1b602959a1a9ace2525fe08550f59","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","build.rs":"fea382a72243440bcfc334229684fecd2e0021f740dd95d2e2df267744cce402","src/bitmap_render_target.rs":"53a172ef42447f8433c5c315f40459c0260a0c44f2ba9ae49ec546d284dd0c73","src/com_helpers.rs":"fccb4b36379ae3454a88aa32a8e5c09e46ef5f5626266dde1fe5f40a992de39c","src/comptr.rs":"218435689f505769686e07cfc5428852dda90b849a0d48e670f632307f5edc7c","src/font.rs":"e792eed304dfcc6ab99d16076d48b5ec941bd18113e506970898a58db4df5d5b","src/font_collection.rs":"969fa3abf141dc3504774886f4783fda4a74cd5a198c643f8a77fc1af4e75258","src/font_face.rs":"f76c3cfef079df9211cf26d67b07140199762293938889a7f4b120eda0427cd5","src/font_family.rs":"403da9f8f9903cbe7f9f79636497b273f9885e200f53af99f9d4e483f11d6889","src/font_file.rs":"60ad02fc25765a2c113175ea372e98a2be0d84aa65fef9246b6a0192e63ff708","src/font_file_loader_impl.rs":"0d304ad99ff1e6874510a1498223329d798ff75b417e3db7e823a695003dfe92","src/gdi_interop.rs":"627a39c72d162308826ac1090972179d39f9962c8e7f29925983744a96862d84","src/glyph_run_analysis.rs":"f816225daa285624f1a1a74c7a5803a1e6b255b494c80cc77760cbc2b45ffbc5","src/helpers.rs":"5d6f164468234ca8806dc1cea117b42dbfae80cc4c9ae965cb0556efdb364682","src/lib.rs":"ae3e07d640aff19442486dfe1501ee797a650598ea7519ee8525a9fa8bbdaa3f","src/rendering_params.rs":"9b132aef922f1ff3df06a1b126eccb6a397e81a04625afdb7b72dc2f968c92cd","src/test.rs":"d77e45f8866abeea070cbbafd4cbde62d875292e8d191310a04c70091978547c","src/types.rs":"53e81cee77c3011b6a82088adf890bd508c779c2ed6d6b0c92502e08d3c21ff0"},"package":"570707c940fc7b7fc627011fe2c8abedaea562b03bde715e3ee2dd3d6857a03c"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"172610b244a5ee8a8e2f1f045058b8abf9291d84bb76bf8779d2fd420419c2d6","Cargo.toml":"abcd85b16e3dd0a0b5213e74b9b23c0ac8e9e484d187588d4f64de717904bc88","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","build.rs":"b40ce243f62825724b4a45092a8e658d71fa952a6840b83f3bee58e719a56d3b","src/bitmap_render_target.rs":"d3b229f85a9804ac52976431657727b410e7d5253283df046e46d98c196f0a3a","src/com_helpers.rs":"fccb4b36379ae3454a88aa32a8e5c09e46ef5f5626266dde1fe5f40a992de39c","src/comptr.rs":"218435689f505769686e07cfc5428852dda90b849a0d48e670f632307f5edc7c","src/font.rs":"9bdf3134c6ad3639eab3da4419c9b43aad2673797f6fdc65841da2c82e1f3af4","src/font_collection.rs":"969fa3abf141dc3504774886f4783fda4a74cd5a198c643f8a77fc1af4e75258","src/font_face.rs":"47fe777fec8102ef665f5c02f57992e3a36c856fc9647ec69d04b7a39828e83b","src/font_family.rs":"403da9f8f9903cbe7f9f79636497b273f9885e200f53af99f9d4e483f11d6889","src/font_file.rs":"60ad02fc25765a2c113175ea372e98a2be0d84aa65fef9246b6a0192e63ff708","src/font_file_loader_impl.rs":"0d304ad99ff1e6874510a1498223329d798ff75b417e3db7e823a695003dfe92","src/gdi_interop.rs":"98922996afc5b8c8304cb65e7c965419003825dfa172a3e11fe69bf3d768551c","src/glyph_run_analysis.rs":"d30d8b41b047815ab5770c730b7a6d09939f2347b4a4257b87bebec08a5794fe","src/helpers.rs":"5d6f164468234ca8806dc1cea117b42dbfae80cc4c9ae965cb0556efdb364682","src/lib.rs":"6f6cc21f3cbe3403beb1d620c59284463a06b588f7344302310b7723b0eafcc2","src/rendering_params.rs":"be1d1c433f76926c285d8ecdb747c5d9cc6a6c10c1a1890c0760cd99755ed471","src/test.rs":"d77e45f8866abeea070cbbafd4cbde62d875292e8d191310a04c70091978547c","src/types.rs":"784235c15d61fb0d001373575169aa473c92af18dcbc1709a5b2bbaa3a7ceb22"},"package":"b5c3d72c5042f43ee02587b5f3256efc6252c2194fbbb0dfa0bd0b6da2491501"}
\ No newline at end of file
--- a/third_party/rust/dwrote/Cargo.toml
+++ b/third_party/rust/dwrote/Cargo.toml
@@ -1,14 +1,14 @@
 [package]
 name = "dwrote"
 description = "Lightweight binding to DirectWrite."
 repository = "https://github.com/vvuk/dwrote-rs"
 license = "MPL-2.0"
-version = "0.1.5"
+version = "0.1.6"
 authors = ["Vladimir Vukicevic <vladimir@pobox.com>"]
 build = "build.rs"
 
 [lib]
 name = "dwrote"
 
 [features]
 default = ["codegen"]
--- a/third_party/rust/dwrote/build.rs
+++ b/third_party/rust/dwrote/build.rs
@@ -1,46 +1,46 @@
-/* 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/. */
-
-#[cfg(all(feature = "serde_codegen", not(feature = "serde_derive")))]
-mod inner {
-    extern crate serde_codegen;
-
-    use std::env;
-    use std::path::Path;
-
-    pub fn main() {
-        let out_dir = env::var_os("OUT_DIR").unwrap();
-
-        let src = Path::new("src/types.rs");
-        let dst = Path::new(&out_dir).join("types.rs");
-
-        serde_codegen::expand(&src, &dst).unwrap();
-        println!("cargo:rerun-if-changed=src/types.rs");
-    }
-}
-
-#[cfg(all(feature = "serde_derive", not(feature = "serde_codegen")))]
-mod inner {
-    pub fn main() {}
-}
-
-#[cfg(all(feature = "serde_codegen", feature = "serde_derive"))]
-mod inner {
-    pub fn main() {
-        panic!("serde_codegen and serde_derive are both used. \
-               You probably forgot --no-default-features.")
-    }
-}
-
-#[cfg(not(any(feature = "serde_codegen", feature = "serde_derive")))]
-mod inner {
-    pub fn main() {
-        panic!("Neither serde_codegen nor serde_derive are used. "
-               "You probably want --features serde_derive --no-default-features.")
-    }
-}
-
-fn main() {
-    inner::main();
-}
+/* 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/. */
+
+#[cfg(all(feature = "serde_codegen", not(feature = "serde_derive")))]
+mod inner {
+    extern crate serde_codegen;
+
+    use std::env;
+    use std::path::Path;
+
+    pub fn main() {
+        let out_dir = env::var_os("OUT_DIR").unwrap();
+
+        let src = Path::new("src/types.rs");
+        let dst = Path::new(&out_dir).join("types.rs");
+
+        serde_codegen::expand(&src, &dst).unwrap();
+        println!("cargo:rerun-if-changed=src/types.rs");
+    }
+}
+
+#[cfg(all(feature = "serde_derive", not(feature = "serde_codegen")))]
+mod inner {
+    pub fn main() {}
+}
+
+#[cfg(all(feature = "serde_codegen", feature = "serde_derive"))]
+mod inner {
+    pub fn main() {
+        panic!("serde_codegen and serde_derive are both used. \
+               You probably forgot --no-default-features.")
+    }
+}
+
+#[cfg(not(any(feature = "serde_codegen", feature = "serde_derive")))]
+mod inner {
+    pub fn main() {
+        panic!("Neither serde_codegen nor serde_derive are used. "
+               "You probably want --features serde_derive --no-default-features.")
+    }
+}
+
+fn main() {
+    inner::main();
+}
--- a/third_party/rust/dwrote/src/bitmap_render_target.rs
+++ b/third_party/rust/dwrote/src/bitmap_render_target.rs
@@ -1,124 +1,124 @@
-/* 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::slice;
-use std::cell::UnsafeCell;
-use std::mem::{zeroed, size_of};
-
-use comptr::ComPtr;
-use winapi;
-use gdi32;
-use super::{FontFace, RenderingParams};
-
-#[derive(Debug)]
-pub struct BitmapRenderTarget {
-    native: UnsafeCell<ComPtr<winapi::IDWriteBitmapRenderTarget>>,
-}
-
-impl BitmapRenderTarget {
-    pub fn take(native: ComPtr<winapi::IDWriteBitmapRenderTarget>) -> BitmapRenderTarget {
-        BitmapRenderTarget {
-            native: UnsafeCell::new(native),
-        }
-    }
-
-    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteBitmapRenderTarget {
-        (*self.native.get()).as_ptr()
-    }
-
-    // A dip is 1/96th of an inch, so this value is the number of pixels per inch divided by 96.
-    pub fn set_pixels_per_dip(&self, ppd: f32) {
-        unsafe {
-            (*self.native.get()).SetPixelsPerDip(ppd);
-        }
-    }
-
-    pub fn get_memory_dc(&self) -> winapi::HDC {
-        unsafe {
-            (*self.native.get()).GetMemoryDC()
-        }
-    }
-
-    pub fn draw_glyph_run(&self,
-                          baseline_origin_x: f32,
-                          baseline_origin_y: f32,
-                          measuring_mode: winapi::DWRITE_MEASURING_MODE,
-                          font_face: &FontFace,
-                          em_size: f32,
-                          glyph_indices: &[u16],
-                          glyph_advances: &[f32],
-                          glyph_offsets: &[winapi::DWRITE_GLYPH_OFFSET],
-                          rendering_params: &RenderingParams,
-                          color: &(f32, f32, f32))
-        -> winapi::RECT
-    {
-        unsafe {
-            assert!(glyph_indices.len() == glyph_advances.len());
-            assert!(glyph_indices.len() == glyph_offsets.len());
-
-            let r = (color.0 * 255.0) as u8;
-            let g = (color.1 * 255.0) as u8;
-            let b = (color.2 * 255.0) as u8;
-
-            let mut glyph_run: winapi::DWRITE_GLYPH_RUN = zeroed();
-            glyph_run.fontFace = font_face.as_ptr();
-            glyph_run.fontEmSize = em_size;
-            glyph_run.glyphCount = glyph_indices.len() as u32;
-            glyph_run.glyphIndices = glyph_indices.as_ptr();
-            glyph_run.glyphAdvances = glyph_advances.as_ptr();
-            glyph_run.glyphOffsets = glyph_offsets.as_ptr();
-            glyph_run.isSideways = 0;
-            glyph_run.bidiLevel = 0;
-
-            let mut rect: winapi::RECT = zeroed();
-            let hr = (*self.native.get()).DrawGlyphRun(baseline_origin_x,
-                                                       baseline_origin_y,
-                                                       measuring_mode,
-                                                       &glyph_run,
-                                                       rendering_params.as_ptr(),
-                                                       winapi::RGB(r,g,b),
-                                                       &mut rect);
-            assert!(hr == 0);
-            rect
-        }
-    }
-
-    // This function expects to have glyphs rendered in WHITE,
-    // and pulls out a u8 vector of width*height*4 size with
-    // the coverage value (we pull out R) broadcast to the alpha
-    // channel, with the color white.  That is, it performs:
-    // RGBX -> xxxR, where xxx = 0xff
-    pub fn get_opaque_values_as_mask(&self) -> Vec<u8> {
-        // Now grossness to pull out the pixels
-        unsafe {
-            let memory_dc = self.get_memory_dc();
-            let mut bitmap: winapi::BITMAP = zeroed();
-            let ret = gdi32::GetObjectW(gdi32::GetCurrentObject(memory_dc, winapi::OBJ_BITMAP),
-                                        size_of::<winapi::BITMAP>() as i32,
-                                        &mut bitmap as *mut _ as *mut winapi::c_void);
-            assert!(ret == size_of::<winapi::BITMAP>() as i32);
-            assert!(bitmap.bmBitsPixel == 32);
-
-            let width = bitmap.bmWidth as usize;
-            let stride = bitmap.bmWidthBytes as usize;
-            let height = bitmap.bmHeight as usize;
-
-            let mut out_bytes: Vec<u8> = vec![0; width * height * 4];
-            let mut out_u32 = slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32,
-                                                        width * height);
-
-            for row in 0..height {
-                let in_offset = (row * stride) as isize;
-                let in_u32 = slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32,
-                                                   width);
-                for col in 0..width {
-                    let r = in_u32[col] & 0xff;
-                    out_u32[width*row + col] = (r << 24) | (0x00ffffffu32);
-                }
-            }
-
-            out_bytes
-        }
-    }
-}
+/* 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::slice;
+use std::cell::UnsafeCell;
+use std::mem::{zeroed, size_of};
+
+use comptr::ComPtr;
+use winapi;
+use gdi32;
+use super::{FontFace, RenderingParams};
+
+#[derive(Debug)]
+pub struct BitmapRenderTarget {
+    native: UnsafeCell<ComPtr<winapi::IDWriteBitmapRenderTarget>>,
+}
+
+impl BitmapRenderTarget {
+    pub fn take(native: ComPtr<winapi::IDWriteBitmapRenderTarget>) -> BitmapRenderTarget {
+        BitmapRenderTarget {
+            native: UnsafeCell::new(native),
+        }
+    }
+
+    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteBitmapRenderTarget {
+        (*self.native.get()).as_ptr()
+    }
+
+    // A dip is 1/96th of an inch, so this value is the number of pixels per inch divided by 96.
+    pub fn set_pixels_per_dip(&self, ppd: f32) {
+        unsafe {
+            (*self.native.get()).SetPixelsPerDip(ppd);
+        }
+    }
+
+    pub fn get_memory_dc(&self) -> winapi::HDC {
+        unsafe {
+            (*self.native.get()).GetMemoryDC()
+        }
+    }
+
+    pub fn draw_glyph_run(&self,
+                          baseline_origin_x: f32,
+                          baseline_origin_y: f32,
+                          measuring_mode: winapi::DWRITE_MEASURING_MODE,
+                          font_face: &FontFace,
+                          em_size: f32,
+                          glyph_indices: &[u16],
+                          glyph_advances: &[f32],
+                          glyph_offsets: &[winapi::DWRITE_GLYPH_OFFSET],
+                          rendering_params: &RenderingParams,
+                          color: &(f32, f32, f32))
+        -> winapi::RECT
+    {
+        unsafe {
+            assert!(glyph_indices.len() == glyph_advances.len());
+            assert!(glyph_indices.len() == glyph_offsets.len());
+
+            let r = (color.0 * 255.0) as u8;
+            let g = (color.1 * 255.0) as u8;
+            let b = (color.2 * 255.0) as u8;
+
+            let mut glyph_run: winapi::DWRITE_GLYPH_RUN = zeroed();
+            glyph_run.fontFace = font_face.as_ptr();
+            glyph_run.fontEmSize = em_size;
+            glyph_run.glyphCount = glyph_indices.len() as u32;
+            glyph_run.glyphIndices = glyph_indices.as_ptr();
+            glyph_run.glyphAdvances = glyph_advances.as_ptr();
+            glyph_run.glyphOffsets = glyph_offsets.as_ptr();
+            glyph_run.isSideways = 0;
+            glyph_run.bidiLevel = 0;
+
+            let mut rect: winapi::RECT = zeroed();
+            let hr = (*self.native.get()).DrawGlyphRun(baseline_origin_x,
+                                                       baseline_origin_y,
+                                                       measuring_mode,
+                                                       &glyph_run,
+                                                       rendering_params.as_ptr(),
+                                                       winapi::RGB(r,g,b),
+                                                       &mut rect);
+            assert!(hr == 0);
+            rect
+        }
+    }
+
+    // This function expects to have glyphs rendered in WHITE,
+    // and pulls out a u8 vector of width*height*4 size with
+    // the coverage value (we pull out R) broadcast to the alpha
+    // channel, with the color white.  That is, it performs:
+    // RGBX -> xxxR, where xxx = 0xff
+    pub fn get_opaque_values_as_mask(&self) -> Vec<u8> {
+        // Now grossness to pull out the pixels
+        unsafe {
+            let memory_dc = self.get_memory_dc();
+            let mut bitmap: winapi::BITMAP = zeroed();
+            let ret = gdi32::GetObjectW(gdi32::GetCurrentObject(memory_dc, winapi::OBJ_BITMAP),
+                                        size_of::<winapi::BITMAP>() as i32,
+                                        &mut bitmap as *mut _ as *mut winapi::c_void);
+            assert!(ret == size_of::<winapi::BITMAP>() as i32);
+            assert!(bitmap.bmBitsPixel == 32);
+
+            let width = bitmap.bmWidth as usize;
+            let stride = bitmap.bmWidthBytes as usize;
+            let height = bitmap.bmHeight as usize;
+
+            let mut out_bytes: Vec<u8> = vec![0; width * height * 4];
+            let mut out_u32 = slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32,
+                                                        width * height);
+
+            for row in 0..height {
+                let in_offset = (row * stride) as isize;
+                let in_u32 = slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32,
+                                                   width);
+                for col in 0..width {
+                    let r = in_u32[col] & 0xff;
+                    out_u32[width*row + col] = (r << 24) | (0x00ffffffu32);
+                }
+            }
+
+            out_bytes
+        }
+    }
+}
--- a/third_party/rust/dwrote/src/font.rs
+++ b/third_party/rust/dwrote/src/font.rs
@@ -1,87 +1,87 @@
-/* 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::cell::UnsafeCell;
-
-use comptr::ComPtr;
-use winapi;
-use std::mem;
-
-use super::*;
-use helpers::*;
-
-#[derive(Debug)]
-pub struct Font {
-    native: UnsafeCell<ComPtr<winapi::IDWriteFont>>,
-}
-
-impl Font {
-    pub fn take(native: ComPtr<winapi::IDWriteFont>) -> Font {
-        Font {
-            native: UnsafeCell::new(native),
-        }
-    }
-
-    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteFont {
-        (*self.native.get()).as_ptr()
-    }
-
-    pub fn to_descriptor(&self) -> FontDescriptor {
-        FontDescriptor {
-            family_name: self.family_name(),
-            stretch: self.stretch(),
-            style: self.style(),
-            weight: self.weight(),
-        }
-    }
-
-    pub fn stretch(&self) -> FontStretch {
-        unsafe {
-            mem::transmute::<u32, FontStretch>((*self.native.get()).GetStretch().0)
-        }
-    }
-
-    pub fn style(&self) -> FontStyle {
-        unsafe {
-            mem::transmute::<u32, FontStyle>((*self.native.get()).GetStyle().0)
-        }
-    }
-
-    pub fn weight(&self) -> FontWeight {
-        unsafe {
-            mem::transmute::<u32, FontWeight>((*self.native.get()).GetWeight().0)
-        }
-    }
-
-    pub fn family_name(&self) -> String {
-        unsafe {
-            let mut family: ComPtr<winapi::IDWriteFontFamily> = ComPtr::new();
-            let hr = (*self.native.get()).GetFontFamily(family.getter_addrefs());
-            assert!(hr == 0);
-
-            FontFamily::take(family).name()
-        }
-    }
-
-    pub fn face_name(&self) -> String {
-        unsafe {
-            let mut names: ComPtr<winapi::IDWriteLocalizedStrings> = ComPtr::new();
-            let hr = (*self.native.get()).GetFaceNames(names.getter_addrefs());
-            assert!(hr == 0);
-
-            get_locale_string(&mut names)
-        }
-    }
-
-    pub fn create_font_face(&self) -> FontFace {
-        // FIXME create_font_face should cache the FontFace and return it,
-        // there's a 1:1 relationship
-        unsafe {
-            let mut face: ComPtr<winapi::IDWriteFontFace> = ComPtr::new();
-            let hr = (*self.native.get()).CreateFontFace(face.getter_addrefs());
-            assert!(hr == 0);
-            FontFace::take(face)
-        }
-    }
-}
+/* 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::cell::UnsafeCell;
+
+use comptr::ComPtr;
+use winapi;
+use std::mem;
+
+use super::*;
+use helpers::*;
+
+#[derive(Debug)]
+pub struct Font {
+    native: UnsafeCell<ComPtr<winapi::IDWriteFont>>,
+}
+
+impl Font {
+    pub fn take(native: ComPtr<winapi::IDWriteFont>) -> Font {
+        Font {
+            native: UnsafeCell::new(native),
+        }
+    }
+
+    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteFont {
+        (*self.native.get()).as_ptr()
+    }
+
+    pub fn to_descriptor(&self) -> FontDescriptor {
+        FontDescriptor {
+            family_name: self.family_name(),
+            stretch: self.stretch(),
+            style: self.style(),
+            weight: self.weight(),
+        }
+    }
+
+    pub fn stretch(&self) -> FontStretch {
+        unsafe {
+            mem::transmute::<u32, FontStretch>((*self.native.get()).GetStretch().0)
+        }
+    }
+
+    pub fn style(&self) -> FontStyle {
+        unsafe {
+            mem::transmute::<u32, FontStyle>((*self.native.get()).GetStyle().0)
+        }
+    }
+
+    pub fn weight(&self) -> FontWeight {
+        unsafe {
+            mem::transmute::<u32, FontWeight>((*self.native.get()).GetWeight().0)
+        }
+    }
+
+    pub fn family_name(&self) -> String {
+        unsafe {
+            let mut family: ComPtr<winapi::IDWriteFontFamily> = ComPtr::new();
+            let hr = (*self.native.get()).GetFontFamily(family.getter_addrefs());
+            assert!(hr == 0);
+
+            FontFamily::take(family).name()
+        }
+    }
+
+    pub fn face_name(&self) -> String {
+        unsafe {
+            let mut names: ComPtr<winapi::IDWriteLocalizedStrings> = ComPtr::new();
+            let hr = (*self.native.get()).GetFaceNames(names.getter_addrefs());
+            assert!(hr == 0);
+
+            get_locale_string(&mut names)
+        }
+    }
+
+    pub fn create_font_face(&self) -> FontFace {
+        // FIXME create_font_face should cache the FontFace and return it,
+        // there's a 1:1 relationship
+        unsafe {
+            let mut face: ComPtr<winapi::IDWriteFontFace> = ComPtr::new();
+            let hr = (*self.native.get()).CreateFontFace(face.getter_addrefs());
+            assert!(hr == 0);
+            FontFace::take(face)
+        }
+    }
+}
--- a/third_party/rust/dwrote/src/font_face.rs
+++ b/third_party/rust/dwrote/src/font_face.rs
@@ -1,137 +1,137 @@
-/* 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::slice;
-use std::ptr;
-use std::cell::UnsafeCell;
-use std::mem::zeroed;
-
-use comptr::ComPtr;
-use super::{FontMetrics, FontFile};
-
-use winapi;
-
-#[derive(Debug)]
-pub struct FontFace {
-    native: UnsafeCell<ComPtr<winapi::IDWriteFontFace>>,
-    metrics: FontMetrics,
-}
-
-impl FontFace {
-    pub fn take(native: ComPtr<winapi::IDWriteFontFace>) -> FontFace {
-        unsafe {
-            let mut metrics: FontMetrics = zeroed();
-            let cell = UnsafeCell::new(native);
-            (*cell.get()).GetMetrics(&mut metrics);
-            FontFace {
-                native: cell,
-                metrics: metrics,
-            }
-        }
-    }
-
-    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteFontFace {
-        (*self.native.get()).as_ptr()
-    }
-
-    pub fn get_files(&self) -> Vec<FontFile> {
-        unsafe {
-            let mut number_of_files: u32 = 0;
-            let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut());
-            assert!(hr == 0);
-
-            let mut file_ptrs: Vec<*mut winapi::IDWriteFontFile> =
-                vec![ptr::null_mut(); number_of_files as usize];
-            let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr());
-            assert!(hr == 0);
-
-            file_ptrs.iter().map(|p| FontFile::take(ComPtr::already_addrefed(*p))).collect()
-        }
-    }
-
-    pub fn get_glyph_count(&self) -> u16 {
-        unsafe {
-            (*self.native.get()).GetGlyphCount()
-        }
-    }
-
-    pub fn metrics(&self) -> &FontMetrics {
-        &self.metrics
-    }
-
-    pub fn get_metrics(&self) -> FontMetrics {
-        unsafe {
-            let mut metrics: winapi::DWRITE_FONT_METRICS = zeroed();
-            (*self.native.get()).GetMetrics(&mut metrics);
-            metrics
-        }
-    }
-
-    pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16> {
-        unsafe {
-            let mut glyph_indices: Vec<u16> = vec![0; code_points.len()];
-            let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(),
-                                                          code_points.len() as u32,
-                                                          glyph_indices.as_mut_ptr());
-            assert!(hr == 0);
-            glyph_indices
-        }
-    }
-
-    pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<winapi::DWRITE_GLYPH_METRICS> {
-        unsafe {
-            let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
-            let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(),
-                                                                glyph_indices.len() as u32,
-                                                                metrics.as_mut_ptr(),
-                                                                is_sideways as winapi::BOOL);
-            assert!(hr == 0);
-            metrics
-        }
-    }
-
-    pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const winapi::DWRITE_MATRIX,
-                                            use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool)
-                                            -> Vec<winapi::DWRITE_GLYPH_METRICS>
-    {
-        unsafe {
-            let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
-            let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip,
-                                                                       transform,
-                                                                       use_gdi_natural as winapi::BOOL,
-                                                                       glyph_indices.as_ptr(),
-                                                                       glyph_indices.len() as u32,
-                                                                       metrics.as_mut_ptr(),
-                                                                       is_sideways as winapi::BOOL);
-            assert!(hr == 0);
-            metrics
-        }
-    }
-
-    pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> {
-        unsafe {
-            let mut table_data_ptr: *const u8 = ptr::null_mut();
-            let mut table_size: u32 = 0;
-            let mut table_context: *mut winapi::c_void = ptr::null_mut();
-            let mut exists: winapi::BOOL = winapi::FALSE;
-
-            let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag,
-                                                          &mut table_data_ptr as *mut *const _ as *mut *const winapi::c_void,
-                                                          &mut table_size,
-                                                          &mut table_context,
-                                                          &mut exists);
-            assert!(hr == 0);
-
-            if exists == winapi::FALSE {
-                return None;
-            }
-
-            let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec();
-
-            (*self.native.get()).ReleaseFontTable(table_context);
-
-            Some(table_bytes)
-        }
-    }
-}
+/* 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::slice;
+use std::ptr;
+use std::cell::UnsafeCell;
+use std::mem::zeroed;
+
+use comptr::ComPtr;
+use super::{FontMetrics, FontFile};
+
+use winapi;
+
+#[derive(Debug)]
+pub struct FontFace {
+    native: UnsafeCell<ComPtr<winapi::IDWriteFontFace>>,
+    metrics: FontMetrics,
+}
+
+impl FontFace {
+    pub fn take(native: ComPtr<winapi::IDWriteFontFace>) -> FontFace {
+        unsafe {
+            let mut metrics: FontMetrics = zeroed();
+            let cell = UnsafeCell::new(native);
+            (*cell.get()).GetMetrics(&mut metrics);
+            FontFace {
+                native: cell,
+                metrics: metrics,
+            }
+        }
+    }
+
+    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteFontFace {
+        (*self.native.get()).as_ptr()
+    }
+
+    pub fn get_files(&self) -> Vec<FontFile> {
+        unsafe {
+            let mut number_of_files: u32 = 0;
+            let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut());
+            assert!(hr == 0);
+
+            let mut file_ptrs: Vec<*mut winapi::IDWriteFontFile> =
+                vec![ptr::null_mut(); number_of_files as usize];
+            let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr());
+            assert!(hr == 0);
+
+            file_ptrs.iter().map(|p| FontFile::take(ComPtr::already_addrefed(*p))).collect()
+        }
+    }
+
+    pub fn get_glyph_count(&self) -> u16 {
+        unsafe {
+            (*self.native.get()).GetGlyphCount()
+        }
+    }
+
+    pub fn metrics(&self) -> &FontMetrics {
+        &self.metrics
+    }
+
+    pub fn get_metrics(&self) -> FontMetrics {
+        unsafe {
+            let mut metrics: winapi::DWRITE_FONT_METRICS = zeroed();
+            (*self.native.get()).GetMetrics(&mut metrics);
+            metrics
+        }
+    }
+
+    pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16> {
+        unsafe {
+            let mut glyph_indices: Vec<u16> = vec![0; code_points.len()];
+            let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(),
+                                                          code_points.len() as u32,
+                                                          glyph_indices.as_mut_ptr());
+            assert!(hr == 0);
+            glyph_indices
+        }
+    }
+
+    pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<winapi::DWRITE_GLYPH_METRICS> {
+        unsafe {
+            let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
+            let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(),
+                                                                glyph_indices.len() as u32,
+                                                                metrics.as_mut_ptr(),
+                                                                is_sideways as winapi::BOOL);
+            assert!(hr == 0);
+            metrics
+        }
+    }
+
+    pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const winapi::DWRITE_MATRIX,
+                                            use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool)
+                                            -> Vec<winapi::DWRITE_GLYPH_METRICS>
+    {
+        unsafe {
+            let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
+            let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip,
+                                                                       transform,
+                                                                       use_gdi_natural as winapi::BOOL,
+                                                                       glyph_indices.as_ptr(),
+                                                                       glyph_indices.len() as u32,
+                                                                       metrics.as_mut_ptr(),
+                                                                       is_sideways as winapi::BOOL);
+            assert!(hr == 0);
+            metrics
+        }
+    }
+
+    pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> {
+        unsafe {
+            let mut table_data_ptr: *const u8 = ptr::null_mut();
+            let mut table_size: u32 = 0;
+            let mut table_context: *mut winapi::c_void = ptr::null_mut();
+            let mut exists: winapi::BOOL = winapi::FALSE;
+
+            let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag,
+                                                          &mut table_data_ptr as *mut *const _ as *mut *const winapi::c_void,
+                                                          &mut table_size,
+                                                          &mut table_context,
+                                                          &mut exists);
+            assert!(hr == 0);
+
+            if exists == winapi::FALSE {
+                return None;
+            }
+
+            let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec();
+
+            (*self.native.get()).ReleaseFontTable(table_context);
+
+            Some(table_bytes)
+        }
+    }
+}
--- a/third_party/rust/dwrote/src/gdi_interop.rs
+++ b/third_party/rust/dwrote/src/gdi_interop.rs
@@ -1,43 +1,43 @@
-/* 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::ptr;
-use std::cell::UnsafeCell;
-
-use comptr::ComPtr;
-use winapi;
-use super::{DWriteFactory, BitmapRenderTarget};
-
-#[derive(Debug)]
-pub struct GdiInterop {
-    native: UnsafeCell<ComPtr<winapi::IDWriteGdiInterop>>,
-}
-
-impl GdiInterop {
-    pub fn create() -> GdiInterop {
-        unsafe {
-            let mut native: ComPtr<winapi::IDWriteGdiInterop> = ComPtr::new();
-            let hr = (*DWriteFactory()).GetGdiInterop(native.getter_addrefs());
-            assert!(hr == 0);
-            GdiInterop::take(native)
-        }
-    }
-
-    pub fn take(native: ComPtr<winapi::IDWriteGdiInterop>) -> GdiInterop {
-        GdiInterop {
-            native: UnsafeCell::new(native),
-        }
-    }
-
-    pub fn create_bitmap_render_target(&self, width: u32, height: u32) -> BitmapRenderTarget {
-        unsafe {
-            let mut native: ComPtr<winapi::IDWriteBitmapRenderTarget> = ComPtr::new();
-            let hr = (*self.native.get()).CreateBitmapRenderTarget(ptr::null_mut(),
-                                                                   width, height,
-                                                                   native.getter_addrefs());
-            assert!(hr == 0);
-            BitmapRenderTarget::take(native)
-        }
-    }
-}
+/* 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::ptr;
+use std::cell::UnsafeCell;
+
+use comptr::ComPtr;
+use winapi;
+use super::{DWriteFactory, BitmapRenderTarget};
+
+#[derive(Debug)]
+pub struct GdiInterop {
+    native: UnsafeCell<ComPtr<winapi::IDWriteGdiInterop>>,
+}
+
+impl GdiInterop {
+    pub fn create() -> GdiInterop {
+        unsafe {
+            let mut native: ComPtr<winapi::IDWriteGdiInterop> = ComPtr::new();
+            let hr = (*DWriteFactory()).GetGdiInterop(native.getter_addrefs());
+            assert!(hr == 0);
+            GdiInterop::take(native)
+        }
+    }
+
+    pub fn take(native: ComPtr<winapi::IDWriteGdiInterop>) -> GdiInterop {
+        GdiInterop {
+            native: UnsafeCell::new(native),
+        }
+    }
+
+    pub fn create_bitmap_render_target(&self, width: u32, height: u32) -> BitmapRenderTarget {
+        unsafe {
+            let mut native: ComPtr<winapi::IDWriteBitmapRenderTarget> = ComPtr::new();
+            let hr = (*self.native.get()).CreateBitmapRenderTarget(ptr::null_mut(),
+                                                                   width, height,
+                                                                   native.getter_addrefs());
+            assert!(hr == 0);
+            BitmapRenderTarget::take(native)
+        }
+    }
+}
--- a/third_party/rust/dwrote/src/glyph_run_analysis.rs
+++ b/third_party/rust/dwrote/src/glyph_run_analysis.rs
@@ -1,72 +1,72 @@
-/* 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::ptr;
-use std::cell::UnsafeCell;
-
-use comptr::ComPtr;
-use winapi;
-use std::mem;
-use super::DWriteFactory;
-
-#[derive(Debug)]
-pub struct GlyphRunAnalysis {
-    native: UnsafeCell<ComPtr<winapi::IDWriteGlyphRunAnalysis>>,
-}
-
-impl GlyphRunAnalysis {
-    pub fn create(glyph_run: &winapi::DWRITE_GLYPH_RUN,
-                  pixels_per_dip: f32,
-                  transform: Option<winapi::DWRITE_MATRIX>,
-                  rendering_mode: winapi::DWRITE_RENDERING_MODE,
-                  measuring_mode: winapi::DWRITE_MEASURING_MODE,
-                  baseline_x: f32,
-                  baseline_y: f32) -> GlyphRunAnalysis
-    {
-        unsafe {
-            let mut native: ComPtr<winapi::IDWriteGlyphRunAnalysis> = ComPtr::new();
-            let hr = (*DWriteFactory()).CreateGlyphRunAnalysis(glyph_run as *const winapi::DWRITE_GLYPH_RUN,
-                                                               pixels_per_dip,
-                                                               transform.as_ref().map(|x| x as *const _).unwrap_or(ptr::null()),
-                                                               rendering_mode, measuring_mode,
-                                                               baseline_x, baseline_y,
-                                                               native.getter_addrefs());
-            assert!(hr == 0);
-            GlyphRunAnalysis::take(native)
-        }
-    }
-
-    pub fn take(native: ComPtr<winapi::IDWriteGlyphRunAnalysis>) -> GlyphRunAnalysis {
-        GlyphRunAnalysis {
-            native: UnsafeCell::new(native),
-        }
-    }
-
-    pub fn get_alpha_texture_bounds(&self, texture_type: winapi::DWRITE_TEXTURE_TYPE) -> winapi::RECT {
-        unsafe {
-            let mut rect: winapi::RECT = mem::zeroed();
-            rect.left = 1234;
-            rect.top = 1234;
-            let hr = (*self.native.get()).GetAlphaTextureBounds(texture_type, &mut rect);
-            assert!(hr == 0);
-            rect
-        }
-    }
-
-    pub fn create_alpha_texture(&self, texture_type: winapi::DWRITE_TEXTURE_TYPE, rect: winapi::RECT) -> Vec<u8> {
-        unsafe {
-            let rect_pixels = (rect.right - rect.left) * (rect.bottom - rect.top);
-            let rect_bytes = rect_pixels * match texture_type {
-                winapi::DWRITE_TEXTURE_ALIASED_1x1 => 1,
-                winapi::DWRITE_TEXTURE_CLEARTYPE_3x1 => 3,
-                _ => panic!("bad texture type specified"),
-            };
-
-            let mut out_bytes: Vec<u8> = vec![0; rect_bytes as usize];
-            let hr = (*self.native.get()).CreateAlphaTexture(texture_type, &rect, out_bytes.as_mut_ptr(), out_bytes.len() as u32);
-            assert!(hr == 0);
-            out_bytes
-        }
-    }
-}
+/* 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::ptr;
+use std::cell::UnsafeCell;
+
+use comptr::ComPtr;
+use winapi;
+use std::mem;
+use super::DWriteFactory;
+
+#[derive(Debug)]
+pub struct GlyphRunAnalysis {
+    native: UnsafeCell<ComPtr<winapi::IDWriteGlyphRunAnalysis>>,
+}
+
+impl GlyphRunAnalysis {
+    pub fn create(glyph_run: &winapi::DWRITE_GLYPH_RUN,
+                  pixels_per_dip: f32,
+                  transform: Option<winapi::DWRITE_MATRIX>,
+                  rendering_mode: winapi::DWRITE_RENDERING_MODE,
+                  measuring_mode: winapi::DWRITE_MEASURING_MODE,
+                  baseline_x: f32,
+                  baseline_y: f32) -> GlyphRunAnalysis
+    {
+        unsafe {
+            let mut native: ComPtr<winapi::IDWriteGlyphRunAnalysis> = ComPtr::new();
+            let hr = (*DWriteFactory()).CreateGlyphRunAnalysis(glyph_run as *const winapi::DWRITE_GLYPH_RUN,
+                                                               pixels_per_dip,
+                                                               transform.as_ref().map(|x| x as *const _).unwrap_or(ptr::null()),
+                                                               rendering_mode, measuring_mode,
+                                                               baseline_x, baseline_y,
+                                                               native.getter_addrefs());
+            assert!(hr == 0);
+            GlyphRunAnalysis::take(native)
+        }
+    }
+
+    pub fn take(native: ComPtr<winapi::IDWriteGlyphRunAnalysis>) -> GlyphRunAnalysis {
+        GlyphRunAnalysis {
+            native: UnsafeCell::new(native),
+        }
+    }
+
+    pub fn get_alpha_texture_bounds(&self, texture_type: winapi::DWRITE_TEXTURE_TYPE) -> winapi::RECT {
+        unsafe {
+            let mut rect: winapi::RECT = mem::zeroed();
+            rect.left = 1234;
+            rect.top = 1234;
+            let hr = (*self.native.get()).GetAlphaTextureBounds(texture_type, &mut rect);
+            assert!(hr == 0);
+            rect
+        }
+    }
+
+    pub fn create_alpha_texture(&self, texture_type: winapi::DWRITE_TEXTURE_TYPE, rect: winapi::RECT) -> Vec<u8> {
+        unsafe {
+            let rect_pixels = (rect.right - rect.left) * (rect.bottom - rect.top);
+            let rect_bytes = rect_pixels * match texture_type {
+                winapi::DWRITE_TEXTURE_ALIASED_1x1 => 1,
+                winapi::DWRITE_TEXTURE_CLEARTYPE_3x1 => 3,
+                _ => panic!("bad texture type specified"),
+            };
+
+            let mut out_bytes: Vec<u8> = vec![0; rect_bytes as usize];
+            let hr = (*self.native.get()).CreateAlphaTexture(texture_type, &rect, out_bytes.as_mut_ptr(), out_bytes.len() as u32);
+            assert!(hr == 0);
+            out_bytes
+        }
+    }
+}
--- a/third_party/rust/dwrote/src/lib.rs
+++ b/third_party/rust/dwrote/src/lib.rs
@@ -57,16 +57,19 @@ pub use winapi::{DWRITE_RENDERING_MODE_D
                  DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC};
 pub use winapi::{DWRITE_MEASURING_MODE_NATURAL,
                  DWRITE_MEASURING_MODE_GDI_CLASSIC,
                  DWRITE_MEASURING_MODE_GDI_NATURAL};
 pub use winapi::{DWRITE_FONT_SIMULATIONS_NONE,
                  DWRITE_FONT_SIMULATIONS_BOLD,
                  DWRITE_FONT_SIMULATIONS_OBLIQUE};
 pub use winapi::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1};
+pub use winapi::{DWRITE_RENDERING_MODE};
+pub use winapi::{DWRITE_MEASURING_MODE};
+pub use winapi::{DWRITE_TEXTURE_TYPE};
 
 #[macro_use] mod com_helpers;
 
 mod bitmap_render_target; pub use bitmap_render_target::BitmapRenderTarget;
 mod font; pub use font::Font;
 mod font_collection; pub use font_collection::FontCollection;
 mod font_face; pub use font_face::FontFace;
 mod font_family; pub use font_family::FontFamily;
--- a/third_party/rust/dwrote/src/rendering_params.rs
+++ b/third_party/rust/dwrote/src/rendering_params.rs
@@ -1,35 +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/. */
-
-use std::cell::UnsafeCell;
-
-use comptr::ComPtr;
-use winapi;
-use super::DWriteFactory;
-
-#[derive(Debug)]
-pub struct RenderingParams {
-    native: UnsafeCell<ComPtr<winapi::IDWriteRenderingParams>>,
-}
-
-impl RenderingParams {
-    pub fn create_for_primary_monitor() -> RenderingParams {
-        unsafe {
-            let mut native: ComPtr<winapi::IDWriteRenderingParams> = ComPtr::new();
-            let hr = (*DWriteFactory()).CreateRenderingParams(native.getter_addrefs());
-            assert!(hr == 0);
-            RenderingParams::take(native)
-        }
-    }
-
-    pub fn take(native: ComPtr<winapi::IDWriteRenderingParams>) -> RenderingParams {
-        RenderingParams {
-            native: UnsafeCell::new(native),
-        }
-    }
-
-    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteRenderingParams {
-        (*self.native.get()).as_ptr()
-    }
-}
+/* 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::cell::UnsafeCell;
+
+use comptr::ComPtr;
+use winapi;
+use super::DWriteFactory;
+
+#[derive(Debug)]
+pub struct RenderingParams {
+    native: UnsafeCell<ComPtr<winapi::IDWriteRenderingParams>>,
+}
+
+impl RenderingParams {
+    pub fn create_for_primary_monitor() -> RenderingParams {
+        unsafe {
+            let mut native: ComPtr<winapi::IDWriteRenderingParams> = ComPtr::new();
+            let hr = (*DWriteFactory()).CreateRenderingParams(native.getter_addrefs());
+            assert!(hr == 0);
+            RenderingParams::take(native)
+        }
+    }
+
+    pub fn take(native: ComPtr<winapi::IDWriteRenderingParams>) -> RenderingParams {
+        RenderingParams {
+            native: UnsafeCell::new(native),
+        }
+    }
+
+    pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteRenderingParams {
+        (*self.native.get()).as_ptr()
+    }
+}
--- a/third_party/rust/dwrote/src/types.rs
+++ b/third_party/rust/dwrote/src/types.rs
@@ -1,80 +1,80 @@
-/* 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/. */
-
-/* this is include!()'d in lib.rs */
-use std::mem;
-
-// mirrors DWRITE_FONT_WEIGHT
-#[repr(u32)]
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
-pub enum FontWeight {
-    Thin = 100,
-    ExtraLight = 200,
-    Light = 300,
-    SemiLight = 350,
-    Regular = 400,
-    Medium = 500,
-    SemiBold = 600,
-    Bold = 700,
-    ExtraBold = 800,
-    Black = 900,
-    ExtraBlack = 950,
-}
-
-impl FontWeight {
-    fn t(&self) -> winapi::DWRITE_FONT_WEIGHT {
-        unsafe { mem::transmute::<FontWeight, winapi::DWRITE_FONT_WEIGHT>(*self) }
-    }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontWeight, u32>(*self) } }
-    pub fn from_u32(v: u32) -> FontWeight { unsafe { mem::transmute::<u32, FontWeight>(v) } }
-}
-
-// mirrors DWRITE_FONT_STRETCH
-#[repr(u32)]
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
-pub enum FontStretch {
-    Undefined = 0,
-    UltraCondensed = 1,
-    ExtraCondensed = 2,
-    Condensed = 3,
-    SemiCondensed = 4,
-    Normal = 5,
-    SemiExpanded = 6,
-    Expanded = 7,
-    ExtraExpanded = 8,
-    UltraExpanded = 9,
-}
-
-impl FontStretch {
-    fn t(&self) -> winapi::DWRITE_FONT_STRETCH {
-        unsafe { mem::transmute::<FontStretch, winapi::DWRITE_FONT_STRETCH>(*self) }
-    }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStretch, u32>(*self) } }
-    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute::<u32, FontStretch>(v) } }
-}
-
-// mirrors DWRITE_FONT_STYLE
-#[repr(u32)]
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
-pub enum FontStyle {
-    Normal = 0,
-    Oblique = 1,
-    Italic = 2,
-}
-
-impl FontStyle {
-    fn t(&self) -> winapi::DWRITE_FONT_STYLE {
-        unsafe { mem::transmute::<FontStyle, winapi::DWRITE_FONT_STYLE>(*self) }
-    }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStyle, u32>(*self) } }
-    pub fn from_u32(v: u32) -> FontStyle { unsafe { mem::transmute::<u32, FontStyle>(v) } }
-}
-
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
-pub struct FontDescriptor {
-    pub family_name: String,
-    pub weight: FontWeight,
-    pub stretch: FontStretch,
-    pub style: FontStyle,
-}
+/* 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/. */
+
+/* this is include!()'d in lib.rs */
+use std::mem;
+
+// mirrors DWRITE_FONT_WEIGHT
+#[repr(u32)]
+#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
+pub enum FontWeight {
+    Thin = 100,
+    ExtraLight = 200,
+    Light = 300,
+    SemiLight = 350,
+    Regular = 400,
+    Medium = 500,
+    SemiBold = 600,
+    Bold = 700,
+    ExtraBold = 800,
+    Black = 900,
+    ExtraBlack = 950,
+}
+
+impl FontWeight {
+    fn t(&self) -> winapi::DWRITE_FONT_WEIGHT {
+        unsafe { mem::transmute::<FontWeight, winapi::DWRITE_FONT_WEIGHT>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontWeight, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontWeight { unsafe { mem::transmute::<u32, FontWeight>(v) } }
+}
+
+// mirrors DWRITE_FONT_STRETCH
+#[repr(u32)]
+#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
+pub enum FontStretch {
+    Undefined = 0,
+    UltraCondensed = 1,
+    ExtraCondensed = 2,
+    Condensed = 3,
+    SemiCondensed = 4,
+    Normal = 5,
+    SemiExpanded = 6,
+    Expanded = 7,
+    ExtraExpanded = 8,
+    UltraExpanded = 9,
+}
+
+impl FontStretch {
+    fn t(&self) -> winapi::DWRITE_FONT_STRETCH {
+        unsafe { mem::transmute::<FontStretch, winapi::DWRITE_FONT_STRETCH>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStretch, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute::<u32, FontStretch>(v) } }
+}
+
+// mirrors DWRITE_FONT_STYLE
+#[repr(u32)]
+#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
+pub enum FontStyle {
+    Normal = 0,
+    Oblique = 1,
+    Italic = 2,
+}
+
+impl FontStyle {
+    fn t(&self) -> winapi::DWRITE_FONT_STYLE {
+        unsafe { mem::transmute::<FontStyle, winapi::DWRITE_FONT_STYLE>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStyle, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontStyle { unsafe { mem::transmute::<u32, FontStyle>(v) } }
+}
+
+#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
+pub struct FontDescriptor {
+    pub family_name: String,
+    pub weight: FontWeight,
+    pub stretch: FontStretch,
+    pub style: FontStyle,
+}
--- a/third_party/rust/gleam/.cargo-checksum.json
+++ b/third_party/rust/gleam/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"46f5e5da873985b56fc97643a27f610feec18724aad8e899379f3b8c84c329ae","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"49e1649ba705e4297e28c1880205c6486524eedfdce4f94c7b395506e973eef0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"5b2abf3e2b85f4d0bdbbaa5778c8fd7480eb151db3bd699ec63b77fa3afdfd7b","src/gl.rs":"712e1bf9b9e75e409920937cc98b0f405f43c809721e1156f6ee5a32cb1ba167","src/lib.rs":"ad33ebcb3f4a0edc36e95c837cda6f01a0be8a6ab1bcf485565fb03f70831324"},"package":"6af023107aa969ccf8868a0304fead4b2f813c19aa9a6a243fddc041f3e51da5"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"46f5e5da873985b56fc97643a27f610feec18724aad8e899379f3b8c84c329ae","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"08c1304ddded710af219247d613a1f5ea16ded3641dfd70a3a8823e131e1e8d5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"5b2abf3e2b85f4d0bdbbaa5778c8fd7480eb151db3bd699ec63b77fa3afdfd7b","src/gl.rs":"feb6da4fc27e8ed2661c5327875323cf129b6709eb7558dde03741af28d60802","src/lib.rs":"ad33ebcb3f4a0edc36e95c837cda6f01a0be8a6ab1bcf485565fb03f70831324"},"package":"7a3023edde169b7767a71d2e5dd8e8903ac3b1436ff659225310928db87d6a8a"}
\ No newline at end of file
--- a/third_party/rust/gleam/Cargo.toml
+++ b/third_party/rust/gleam/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "gleam"
-version = "0.2.30"
+version = "0.2.31"
 license = "Apache-2.0/MIT"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 documentation = "http://doc.servo.org/gleam/"
 repository = "https://github.com/servo/gleam"
 description = "Generated OpenGL bindings and wrapper for Servo."
 
 [build-dependencies]
--- a/third_party/rust/gleam/src/gl.rs
+++ b/third_party/rust/gleam/src/gl.rs
@@ -920,16 +920,37 @@ pub fn is_shader(shader: GLuint) -> GLbo
 #[inline]
 pub fn is_texture(texture: GLenum) -> GLboolean {
     unsafe {
         ffi::IsTexture(texture)
     }
 }
 
 #[inline]
+pub fn is_framebuffer(framebuffer: GLenum) -> GLboolean {
+    unsafe {
+        ffi::IsFramebuffer(framebuffer)
+    }
+}
+
+#[inline]
+pub fn is_renderbuffer(renderbuffer: GLenum) -> GLboolean {
+    unsafe {
+        ffi::IsRenderbuffer(renderbuffer)
+    }
+}
+
+#[inline]
+pub fn check_frame_buffer_status(target: GLenum) -> GLenum {
+    unsafe {
+        ffi::CheckFramebufferStatus(target)
+    }
+}
+
+#[inline]
 pub fn enable_vertex_attrib_array(index: GLuint) {
     unsafe {
         ffi::EnableVertexAttribArray(index);
     }
 }
 
 #[inline]
 pub fn disable_vertex_attrib_array(index: GLuint) {
--- a/third_party/rust/offscreen_gl_context/.cargo-checksum.json
+++ b/third_party/rust/offscreen_gl_context/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"9b8376fc479996f32f8a690e6009fc2f7e9f6dc1b1224e0180a92ad65b0b2183","Cargo.toml":"dc0cd165e159c1c8a3300fde9ee2b19a61e0c9f6ec8fc3cf96eede9724bad910","Makefile":"85b6d903eecac170ac97f10d9d89b8366cd91f5ea2f7c6212704bc590b64cf50","README.md":"614cf0c6242be3e62e45a3d60ce9a2a1581bdc46b28b25d5f40caba558e4d615","build.rs":"86776b47fac1d9368e3c3c5d57c62731729ed859bb1c4e4db0fe219251812cab","src/draw_buffer.rs":"7619ea2889c1e49ea387c3952a8cea5821526cf68e81ad02f918a373e71ef9ed","src/gl_context.rs":"18ccf931fb9a19bc3e0b7ddec8a5bfc2557357d8874e3e0e5c72a3073bc4d053","src/gl_context_attributes.rs":"c76ef02996d0daac313b666d1991878bbf7812932a0f9feac9e62c89ba7bf669","src/gl_context_capabilities.rs":"9f665ad04d42d47d15ecbd430639d95da526ec5951f0b7abe2434adc1415c85d","src/gl_feature.rs":"b826884900c0e8d6317a41ebb6c30bdb468601bf1c030c376749bdb2ecd2f15a","src/gl_formats.rs":"99087345b4e9a12c86605c0d091bfaf1b4ed4b2475a3b6f91d2127a2bb85fe1b","src/gl_limits.rs":"02e41619518daae5895929db00d073b5ad0d9daf9319a61abb7012c2e59fb6c7","src/lib.rs":"daaf4e26504dbb97f3803de4337f601d616adf0633e5c4415c2c172fb257ebd6","src/platform/mod.rs":"f6ec310e5b8fb519607b8e4d5ca71a0c07c83737a83c3785b5b44e7902498c8a","src/platform/not_implemented/mod.rs":"d576e9fc3164f9e2a8ff9460a60eaa8ecada44c600de1a4d1bb5513ab93569af","src/platform/not_implemented/native_gl_context.rs":"fe018722b8bebbd59b6fae759dd78b0175d10bf110205b113ff155fd06d0f75d","src/platform/with_cgl/mod.rs":"b05dc146c9ba82d62410d9b0566a8aa70c77e7ec583ad4881c531d7118454543","src/platform/with_cgl/native_gl_context.rs":"c6271cfa96836d8f833f5efbc90352852557d582db41d2c513cc36c3f966ae88","src/platform/with_egl/mod.rs":"c52ac147eb051733070c36b2c62be8c57427f80999507f62a9ce801f4aac284c","src/platform/with_egl/native_gl_context.rs":"3a8342d53de9525a5478cc96b323dbad2b3628aa6655fe5f092834cc72256116","src/platform/with_egl/utils.rs":"508521e2bf3809ffe0dfea4fa4a358903f49c77a33aa42cc6c0e7458d992a2a7","src/platform/with_glx/mod.rs":"0e497f38b2071ed189995c91b27b0b199d31bfcc10836e2d26b55023d7aff503","src/platform/with_glx/native_gl_context.rs":"2c648ae18baac14290b2eca3581d474adfea00a29a7ad47a1100e564e74b9152","src/platform/with_glx/utils.rs":"eb81e0a4c62947fa5099c241cfe2e4dd075376d30b22864e042c0f536ac6be58","src/platform/with_osmesa/mod.rs":"9f6d69878125185f16740f52ba5cdd8a45e8812af1a3561482c9b43edaf4514a","src/platform/with_wgl/mod.rs":"38f9b44b54c8a1bd4d25ae77a4ea6a2e5454a00b816764d7d74152c1f3c1b126","src/platform/with_wgl/native_gl_context.rs":"4aecd40a811cf38607b17db9724f79bb934e056f85c90c987b2aa82d637b7bb4","src/platform/with_wgl/utils.rs":"d9640c000dcb513cf0a13c4a0d35c423366b7d0894deff299affe0202bdeb770","src/platform/with_wgl/wgl_attributes.rs":"73b75da18519e048011e9c303e402cf7961e3652aa8f4d4ebf507b4ab83d06a3","src/tests.rs":"780d4211a02c09abebb2b8be85a87ed98bee374999bd333c29efb3a8c7d2b281"},"package":"2fe2fe54ba2b6ea8f43a17b16c13168c5bbf008e0fc91b34122a11f637e2728a"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"9b8376fc479996f32f8a690e6009fc2f7e9f6dc1b1224e0180a92ad65b0b2183","Cargo.toml":"a2aacf8d637addcb13f6f04e21c65ae4bde00bb589de00b8c97746224a97499c","Makefile":"85b6d903eecac170ac97f10d9d89b8366cd91f5ea2f7c6212704bc590b64cf50","README.md":"614cf0c6242be3e62e45a3d60ce9a2a1581bdc46b28b25d5f40caba558e4d615","build.rs":"86776b47fac1d9368e3c3c5d57c62731729ed859bb1c4e4db0fe219251812cab","src/draw_buffer.rs":"52bef86972f40e0dd13a6e81f3aa76d4d0c28ea0b63f5f9da9650a34d75488c0","src/gl_context.rs":"28953e3752ea7fd2b19327f98c06fe53f7618efc4d3f0cb2262eba403756df2a","src/gl_context_attributes.rs":"c76ef02996d0daac313b666d1991878bbf7812932a0f9feac9e62c89ba7bf669","src/gl_context_capabilities.rs":"9f665ad04d42d47d15ecbd430639d95da526ec5951f0b7abe2434adc1415c85d","src/gl_feature.rs":"b826884900c0e8d6317a41ebb6c30bdb468601bf1c030c376749bdb2ecd2f15a","src/gl_formats.rs":"99087345b4e9a12c86605c0d091bfaf1b4ed4b2475a3b6f91d2127a2bb85fe1b","src/gl_limits.rs":"02e41619518daae5895929db00d073b5ad0d9daf9319a61abb7012c2e59fb6c7","src/lib.rs":"daaf4e26504dbb97f3803de4337f601d616adf0633e5c4415c2c172fb257ebd6","src/platform/mod.rs":"f6ec310e5b8fb519607b8e4d5ca71a0c07c83737a83c3785b5b44e7902498c8a","src/platform/not_implemented/mod.rs":"d576e9fc3164f9e2a8ff9460a60eaa8ecada44c600de1a4d1bb5513ab93569af","src/platform/not_implemented/native_gl_context.rs":"fe018722b8bebbd59b6fae759dd78b0175d10bf110205b113ff155fd06d0f75d","src/platform/with_cgl/mod.rs":"b05dc146c9ba82d62410d9b0566a8aa70c77e7ec583ad4881c531d7118454543","src/platform/with_cgl/native_gl_context.rs":"c6271cfa96836d8f833f5efbc90352852557d582db41d2c513cc36c3f966ae88","src/platform/with_egl/mod.rs":"c52ac147eb051733070c36b2c62be8c57427f80999507f62a9ce801f4aac284c","src/platform/with_egl/native_gl_context.rs":"3a8342d53de9525a5478cc96b323dbad2b3628aa6655fe5f092834cc72256116","src/platform/with_egl/utils.rs":"508521e2bf3809ffe0dfea4fa4a358903f49c77a33aa42cc6c0e7458d992a2a7","src/platform/with_glx/mod.rs":"0e497f38b2071ed189995c91b27b0b199d31bfcc10836e2d26b55023d7aff503","src/platform/with_glx/native_gl_context.rs":"2c648ae18baac14290b2eca3581d474adfea00a29a7ad47a1100e564e74b9152","src/platform/with_glx/utils.rs":"eb81e0a4c62947fa5099c241cfe2e4dd075376d30b22864e042c0f536ac6be58","src/platform/with_osmesa/mod.rs":"9f6d69878125185f16740f52ba5cdd8a45e8812af1a3561482c9b43edaf4514a","src/platform/with_wgl/mod.rs":"38f9b44b54c8a1bd4d25ae77a4ea6a2e5454a00b816764d7d74152c1f3c1b126","src/platform/with_wgl/native_gl_context.rs":"4aecd40a811cf38607b17db9724f79bb934e056f85c90c987b2aa82d637b7bb4","src/platform/with_wgl/utils.rs":"d9640c000dcb513cf0a13c4a0d35c423366b7d0894deff299affe0202bdeb770","src/platform/with_wgl/wgl_attributes.rs":"73b75da18519e048011e9c303e402cf7961e3652aa8f4d4ebf507b4ab83d06a3","src/tests.rs":"780d4211a02c09abebb2b8be85a87ed98bee374999bd333c29efb3a8c7d2b281"},"package":"2092c6bb5550536a097c5b413a2c36e141bc63c85c0a40944a182c1912d69397"}
\ No newline at end of file
--- a/third_party/rust/offscreen_gl_context/Cargo.toml
+++ b/third_party/rust/offscreen_gl_context/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
 name = "offscreen_gl_context"
 license = "MIT / Apache-2.0"
-version = "0.5.1"
+version = "0.5.3"
 authors = ["Emilio Cobos Álvarez <ecoal95@gmail.com>", "The Servo Project Developers"]
 description = "Creation and manipulation of HW accelerated offscreen rendering contexts in multiple platforms. Originally intended for the Servo project's WebGL implementation."
 repository = "https://github.com/emilio/rust-offscreen-rendering-context"
 build = "build.rs"
 
 [build-dependencies]
 gl_generator = "0.5"
 
--- a/third_party/rust/offscreen_gl_context/src/draw_buffer.rs
+++ b/third_party/rust/offscreen_gl_context/src/draw_buffer.rs
@@ -1,17 +1,15 @@
 use euclid::Size2D;
 use gleam::gl;
 use gleam::gl::types::{GLuint, GLenum, GLint};
 
 use GLContext;
 use NativeGLContextMethods;
 
-use std::ptr;
-
 #[derive(Debug)]
 pub enum ColorAttachmentType {
     Texture,
     Renderbuffer,
 }
 
 impl Default for ColorAttachmentType {
     fn default() -> ColorAttachmentType {
@@ -36,21 +34,19 @@ impl ColorAttachment {
             ColorAttachment::Renderbuffer(_) => ColorAttachmentType::Renderbuffer,
             ColorAttachment::Texture(_) => ColorAttachmentType::Texture,
         }
     }
 }
 
 impl Drop for ColorAttachment {
     fn drop(&mut self) {
-        unsafe {
-            match *self {
-                ColorAttachment::Renderbuffer(mut id) => gl::DeleteRenderbuffers(1, &mut id),
-                ColorAttachment::Texture(mut tex_id) => gl::DeleteTextures(1, &mut tex_id),
-            }
+        match *self {
+            ColorAttachment::Renderbuffer(id) => gl::delete_renderbuffers(&[id]),
+            ColorAttachment::Texture(tex_id) => gl::delete_textures(&[tex_id]),
         }
     }
 }
 
 /// This structure represents an offscreen context
 /// draw buffer. It has a framebuffer, with at least
 /// color renderbuffer (alpha or not). It may also have
 /// a depth or stencil buffer, depending on context
@@ -64,24 +60,20 @@ pub struct DrawBuffer {
     // samples: GLsizei,
 }
 
 /// Helper function to create a render buffer
 /// TODO(ecoal95): We'll need to switch between `glRenderbufferStorage` and
 ///   `glRenderbufferStorageMultisample` when we support antialising
 fn create_renderbuffer(format: GLenum,
                        size: &Size2D<i32>) -> GLuint {
-    let mut ret: GLuint = 0;
-
-    unsafe {
-        gl::GenRenderbuffers(1, &mut ret);
-        gl::BindRenderbuffer(gl::RENDERBUFFER, ret);
-        gl::RenderbufferStorage(gl::RENDERBUFFER, format, size.width, size.height);
-        gl::BindRenderbuffer(gl::RENDERBUFFER, 0);
-    }
+    let ret = gl::gen_renderbuffers(1)[0];
+    gl::bind_renderbuffer(gl::RENDERBUFFER, ret);
+    gl::renderbuffer_storage(gl::RENDERBUFFER, format, size.width, size.height);
+    gl::bind_renderbuffer(gl::RENDERBUFFER, 0);
 
     ret
 }
 
 impl DrawBuffer {
     pub fn new<T: NativeGLContextMethods>(context: &GLContext<T>,
                                           mut size: Size2D<i32>,
                                           color_attachment_type: ColorAttachmentType)
@@ -116,20 +108,18 @@ impl DrawBuffer {
             depth_renderbuffer: 0,
             // samples: 0,
         };
 
         try!(context.make_current());
 
         try!(draw_buffer.init(context, color_attachment_type));
 
-        unsafe {
-            debug_assert!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE);
-            debug_assert!(gl::get_error() == gl::NO_ERROR);
-        }
+        debug_assert!(gl::check_frame_buffer_status(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE);
+        debug_assert!(gl::get_error() == gl::NO_ERROR);
 
         Ok(draw_buffer)
     }
 
     #[inline(always)]
     pub fn get_framebuffer(&self) -> GLuint {
         self.framebuffer
     }
@@ -162,28 +152,21 @@ impl DrawBuffer {
 }
 
 // NOTE: The initially associated GLContext MUST be the current gl context
 // when drop is called. I know this is an important constraint.
 // Right now there are no problems, if not, consider using a pointer to a
 // parent with Rc<GLContext> and call make_current()
 impl Drop for DrawBuffer {
     fn drop(&mut self) {
-        unsafe {
-            gl::DeleteFramebuffers(1, &mut self.framebuffer);
+        gl::delete_framebuffers(&[self.framebuffer]);
 
-            // NOTE: Color renderbuffer is destroyed on drop of
-            //   ColorAttachment
-            let mut renderbuffers = [
-                self.stencil_renderbuffer,
-                self.depth_renderbuffer
-            ];
-
-            gl::DeleteRenderbuffers(2, renderbuffers.as_mut_ptr());
-        }
+        // NOTE: Color renderbuffer is destroyed on drop of
+        //   ColorAttachment
+        gl::delete_renderbuffers(&[self.stencil_renderbuffer, self.depth_renderbuffer]);
     }
 }
 
 trait DrawBufferHelpers {
     fn init<T: NativeGLContextMethods>(&mut self,
                                        &GLContext<T>,
                                        color_attachment_type: ColorAttachmentType)
         -> Result<(), &'static str>;
@@ -204,98 +187,89 @@ impl DrawBufferHelpers for DrawBuffer {
                 let color_renderbuffer = create_renderbuffer(formats.color_renderbuffer, &self.size);
                 debug_assert!(color_renderbuffer != 0);
 
                 Some(ColorAttachment::Renderbuffer(color_renderbuffer))
             },
 
             // TODO(ecoal95): Allow more customization of textures
             ColorAttachmentType::Texture => {
-                let mut texture = 0;
+                let texture = gl::gen_textures(1)[0];
+                debug_assert!(texture != 0);
 
-                // TODO(ecoal95): Check gleam safe wrappers for these functions
-                unsafe {
-                    gl::GenTextures(1, &mut texture);
-                    debug_assert!(texture != 0);
-
-                    gl::BindTexture(gl::TEXTURE_2D, texture);
-                    gl::TexImage2D(gl::TEXTURE_2D, 0,
-                                   formats.texture_internal as GLint, self.size.width, self.size.height, 0, formats.texture, formats.texture_type, ptr::null_mut());
+                gl::bind_texture(gl::TEXTURE_2D, texture);
+                gl::tex_image_2d(gl::TEXTURE_2D, 0,
+                                 formats.texture_internal as GLint, self.size.width, self.size.height, 0, formats.texture, formats.texture_type, None);
 
-                    // Low filtering to allow rendering
-                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
-                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
+                // Low filtering to allow rendering
+                gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
+                gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
 
-                    // TODO(ecoal95): Check if these two are neccessary, probably not
-                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
-                    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
+                // TODO(ecoal95): Check if these two are neccessary, probably not
+                gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
+                gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
 
-                    gl::BindTexture(gl::TEXTURE_2D, 0);
+                gl::bind_texture(gl::TEXTURE_2D, 0);
 
-                    debug_assert!(gl::get_error() == gl::NO_ERROR);
+                debug_assert!(gl::get_error() == gl::NO_ERROR);
 
-                    Some(ColorAttachment::Texture(texture))
-                }
+                Some(ColorAttachment::Texture(texture))
             },
         };
 
         // After this we check if we need stencil and depth buffers
         if attrs.depth {
             self.depth_renderbuffer = create_renderbuffer(formats.depth, &self.size);
             debug_assert!(self.depth_renderbuffer != 0);
         }
 
         if attrs.stencil {
             self.stencil_renderbuffer = create_renderbuffer(formats.stencil, &self.size);
             debug_assert!(self.stencil_renderbuffer != 0);
         }
 
-        unsafe {
-            gl::GenFramebuffers(1, &mut self.framebuffer);
-            debug_assert!(self.framebuffer != 0);
-        }
+        self.framebuffer = gl::gen_framebuffers(1)[0];
+        debug_assert!(self.framebuffer != 0);
 
         // Finally we attach them to the framebuffer
         self.attach_to_framebuffer()
     }
 
     fn attach_to_framebuffer(&mut self) -> Result<(), &'static str> {
-        unsafe {
-            gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer);
-            // NOTE: The assertion fails if the framebuffer is not bound
-            debug_assert!(gl::IsFramebuffer(self.framebuffer) == gl::TRUE);
+        gl::bind_framebuffer(gl::FRAMEBUFFER, self.framebuffer);
+        // NOTE: The assertion fails if the framebuffer is not bound
+        debug_assert!(gl::is_framebuffer(self.framebuffer) == gl::TRUE);
 
-            match *self.color_attachment.as_ref().unwrap() {
-                ColorAttachment::Renderbuffer(color_renderbuffer) => {
-                    gl::FramebufferRenderbuffer(gl::FRAMEBUFFER,
-                                                gl::COLOR_ATTACHMENT0,
-                                                gl::RENDERBUFFER,
-                                                color_renderbuffer);
-                    debug_assert!(gl::IsRenderbuffer(color_renderbuffer) == gl::TRUE);
-                },
-                ColorAttachment::Texture(texture_id) => {
-                    gl::FramebufferTexture2D(gl::FRAMEBUFFER,
+        match *self.color_attachment.as_ref().unwrap() {
+            ColorAttachment::Renderbuffer(color_renderbuffer) => {
+                gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
                                              gl::COLOR_ATTACHMENT0,
-                                             gl::TEXTURE_2D,
-                                             texture_id, 0);
-                },
-            }
+                                             gl::RENDERBUFFER,
+                                             color_renderbuffer);
+                debug_assert!(gl::is_renderbuffer(color_renderbuffer) == gl::TRUE);
+            },
+            ColorAttachment::Texture(texture_id) => {
+                gl::framebuffer_texture_2d(gl::FRAMEBUFFER,
+                                           gl::COLOR_ATTACHMENT0,
+                                           gl::TEXTURE_2D,
+                                           texture_id, 0);
+            },
+        }
 
-            if self.depth_renderbuffer != 0 {
-                gl::FramebufferRenderbuffer(gl::FRAMEBUFFER,
-                                            gl::DEPTH_ATTACHMENT,
-                                            gl::RENDERBUFFER,
-                                            self.depth_renderbuffer);
-                debug_assert!(gl::IsRenderbuffer(self.depth_renderbuffer) == gl::TRUE);
-            }
+        if self.depth_renderbuffer != 0 {
+            gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
+                                         gl::DEPTH_ATTACHMENT,
+                                         gl::RENDERBUFFER,
+                                         self.depth_renderbuffer);
+            debug_assert!(gl::is_renderbuffer(self.depth_renderbuffer) == gl::TRUE);
+        }
 
-            if self.stencil_renderbuffer != 0 {
-                gl::FramebufferRenderbuffer(gl::FRAMEBUFFER,
-                                            gl::STENCIL_ATTACHMENT,
-                                            gl::RENDERBUFFER,
-                                            self.stencil_renderbuffer);
-                debug_assert!(gl::IsRenderbuffer(self.stencil_renderbuffer) == gl::TRUE);
-            }
+        if self.stencil_renderbuffer != 0 {
+            gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
+                                         gl::STENCIL_ATTACHMENT,
+                                         gl::RENDERBUFFER,
+                                         self.stencil_renderbuffer);
+            debug_assert!(gl::is_renderbuffer(self.stencil_renderbuffer) == gl::TRUE);
         }
 
         Ok(())
     }
 }
--- a/third_party/rust/offscreen_gl_context/src/gl_context.rs
+++ b/third_party/rust/offscreen_gl_context/src/gl_context.rs
@@ -1,11 +1,11 @@
 use euclid::Size2D;
 use gleam::gl;
-use gleam::gl::types::{GLint, GLuint};
+use gleam::gl::types::{GLuint};
 
 use NativeGLContextMethods;
 use GLContextAttributes;
 use GLContextCapabilities;
 use GLFormats;
 use GLLimits;
 use DrawBuffer;
 use ColorAttachmentType;
@@ -136,21 +136,18 @@ impl<Native> GLContext<Native>
         self.draw_buffer.as_ref()
     }
 
     pub fn get_framebuffer(&self) -> GLuint {
         if let Some(ref db) = self.draw_buffer {
             return db.get_framebuffer();
         }
 
-        unsafe {
-            let mut ret : GLint = 0;
-            gl::GetIntegerv(gl::FRAMEBUFFER_BINDING, &mut ret);
-            ret as GLuint
-        }
+        let ret = gl::get_integer_v(gl::FRAMEBUFFER_BINDING);
+        ret as GLuint
     }
 
     pub fn draw_buffer_size(&self) -> Option<Size2D<i32>> {
         self.draw_buffer.as_ref().map( |db| db.size() )
     }
 
     // We resize just replacing the draw buffer, we don't perform size optimizations
     // in order to keep this generic
@@ -178,22 +175,20 @@ trait GLContextPrivateMethods {
 }
 
 impl<T: NativeGLContextMethods> GLContextPrivateMethods for GLContext<T> {
     fn init_offscreen(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
         try!(self.create_draw_buffer(size, color_attachment_type));
 
         debug_assert!(self.is_current());
 
-        unsafe {
-            gl::ClearColor(0.0, 0.0, 0.0, 0.0);
-            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
-            gl::Scissor(0, 0, size.width, size.height);
-            gl::Viewport(0, 0, size.width, size.height);
-        }
+        gl::clear_color(0.0, 0.0, 0.0, 0.0);
+        gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
+        gl::scissor(0, 0, size.width, size.height);
+        gl::viewport(0, 0, size.width, size.height);
 
         Ok(())
     }
 
     fn create_draw_buffer(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
         self.draw_buffer = Some(try!(DrawBuffer::new(&self, size, color_attachment_type)));
         Ok(())
     }
--- a/third_party/rust/pkg-config/.cargo-checksum.json
+++ b/third_party/rust/pkg-config/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"8d7877933bd1dbc8e7d45491cfeffb596e99f007b87d1704fbcbb1e2907aa55d","Cargo.toml":"6b8bd4b975acf4a3b8fca56990bafcb7e30fea391a754e0ed79a2eab61891c32","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"24788a22c94dd50f248fb7baa1520acf5a02f000600a9b5a8bb9ab5bde5c35a8","src/lib.rs":"1b110ac5e75501837db190de3a39b3d2f202dd71289a1087483d61f1f7d31359","tests/foo.pc":"f77712847e77ea81ac6362de5861dc0eddf14b9c07dce1853b3e3e587ffcac5e","tests/framework.pc":"4d02091799252777afb0547321cc04e7df1e017226a6b05630fed5eaf37e0125","tests/test.rs":"1a842822fc56bac88efa9d604061b5d88e03faa8efb23cdfbdd86f6a6c2ca2c9"},"package":"8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"f2b3b481e61dee9f83649f2079c7637fef1f3e4c181926bf77d39128f3ea82c7","Cargo.toml":"425339eef4a01cf8773dc69444115e5771c84194f68f1748a22b0c0f200dd475","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"6259efd2a3ba18ea50579f0af2ef3d4e797231522e18bad915ca25901fb31de2","src/lib.rs":"163a48484a96ab21529b42bfe3448753c898a42f4b204aa352bf0f87ff49f30e","tests/foo.pc":"f77712847e77ea81ac6362de5861dc0eddf14b9c07dce1853b3e3e587ffcac5e","tests/framework.pc":"4d02091799252777afb0547321cc04e7df1e017226a6b05630fed5eaf37e0125","tests/test.rs":"09bf2811e3d58432080a76b0d297131e43d215253894a2919626e71b30924b0b"},"package":"3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"}
\ No newline at end of file
--- a/third_party/rust/pkg-config/.travis.yml
+++ b/third_party/rust/pkg-config/.travis.yml
@@ -1,25 +1,23 @@
 language: rust
 rust:
   - stable
   - beta
   - nightly
 sudo: false
+before_script:
+  - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
 script:
   - cargo build --verbose
-  - |
-    [ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose
-  - cargo doc
-after_success: |
-  [ $TRAVIS_BRANCH = master ] &&
-  [ $TRAVIS_PULL_REQUEST = false ] &&
-  [ $TRAVIS_RUST_VERSION = nightly ] &&
-  echo '<meta http-equiv=refresh content=0;url=pkg_config/index.html>' > target/doc/index.html &&
-  pip install ghp-import --user $USER &&
-  $HOME/.local/bin/ghp-import -n target/doc &&
-  git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
+  - cargo test --verbose
+  - cargo doc --no-deps
+after_success:
+  - travis-cargo --only nightly doc-upload
 env:
   global:
-    secure: XlfwiQ+fPgRWqFwHbyPTma2FAVtgN+IXFpkiIdh1sKxWEeHMqABrTtOKf/NugDYCGsOJfr2vb5qFL6teBV2lTXOffUIWj+1hMd0N/FbVKWzABBV02XdxQi8w2ptPez5LPRTEfXJRRHmJpc8ww2aCTIrdT3AQE2oqZM/jHJTi/1U=
+    secure: "D/GKEEBQarjXTZ6NWzwQq39nQ892XJ9m3C9219K/6Us8jyjE5DBhosDPvg6pvRJtTLaghDxuhxqkHunayNL18IOvkNbfMjYsnkP8/yMftQUfRdNub6C1kXAi8guXjPd8rUwW0Oy8Nar61WAwWQgHkXfuSJ2em7u/Xk0tICPSwlA="
+
+
+
 notifications:
   email:
     on_success: never
--- a/third_party/rust/pkg-config/Cargo.toml
+++ b/third_party/rust/pkg-config/Cargo.toml
@@ -1,13 +1,16 @@
 [package]
 
 name = "pkg-config"
-version = "0.3.8"
+version = "0.3.9"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/alexcrichton/pkg-config-rs"
-documentation = "http://alexcrichton.com/pkg-config-rs"
+documentation = "https://docs.rs/pkg-config"
 description = """
 A library to run the pkg-config system tool at build time in order to be used in
 Cargo build scripts.
 """
 keywords = ["build-dependencies"]
+
+[dev-dependencies]
+lazy_static = "0.2"
--- a/third_party/rust/pkg-config/README.md
+++ b/third_party/rust/pkg-config/README.md
@@ -1,23 +1,42 @@
 # pkg-config-rs
 
 [![Build Status](https://travis-ci.org/alexcrichton/pkg-config-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/pkg-config-rs)
 
-[Documentation](http://alexcrichton.com/pkg-config-rs)
+[Documentation](https://docs.rs/pkg-config)
 
 A simple library meant to be used as a build dependency with Cargo packages in
 order to use the system `pkg-config` tool (if available) to determine where a
 library is located.
 
+You can use this crate directly to probe for specific libraries, or use
+[metadeps](https://github.com/joshtriplett/metadeps) to declare all your
+`pkg-config` dependencies in `Cargo.toml`.
+
+# Example
+
+Find the system library named `foo`, with minimum version 1.2.3:
+
 ```rust
 extern crate pkg_config;
 
 fn main() {
-    pkg_config::find_library("foo").unwrap();
+    pkg_config::Config::new().atleast_version("1.2.3").probe("foo").unwrap();
+}
+```
+
+Find the system library named `foo`, with no version requirement (not
+recommended):
+
+```rust
+extern crate pkg_config;
+
+fn main() {
+    pkg_config::probe_library("foo").unwrap();
 }
 ```
 
 # License
 
 `pkg-config-rs` is primarily distributed under the terms of both the MIT
 license and the Apache License (Version 2.0), with portions covered by various
 BSD-like licenses.
--- a/third_party/rust/pkg-config/src/lib.rs
+++ b/third_party/rust/pkg-config/src/lib.rs
@@ -25,37 +25,48 @@
 //! * `PKG_CONFIG_ALL_STATIC` - pass `--static` for all libraries
 //! * `PKG_CONFIG_ALL_DYNAMIC` - do not pass `--static` for all libraries
 //!
 //! After running `pkg-config` all appropriate Cargo metadata will be printed on
 //! stdout if the search was successful.
 //!
 //! # Example
 //!
-//! Find the system library named `foo`.
+//! Find the system library named `foo`, with minimum version 1.2.3:
+//!
+//! ```no_run
+//! extern crate pkg_config;
+//!
+//! fn main() {
+//!     pkg_config::Config::new().atleast_version("1.2.3").probe("foo").unwrap();
+//! }
+//! ```
+//!
+//! Find the system library named `foo`, with no version requirement (not
+//! recommended):
 //!
 //! ```no_run
 //! extern crate pkg_config;
 //!
 //! fn main() {
 //!     pkg_config::probe_library("foo").unwrap();
 //! }
 //! ```
 //!
 //! Configure how library `foo` is linked to.
 //!
 //! ```no_run
 //! extern crate pkg_config;
 //!
 //! fn main() {
-//!     pkg_config::Config::new().statik(true).probe("foo").unwrap();
+//!     pkg_config::Config::new().atleast_version("1.2.3").statik(true).probe("foo").unwrap();
 //! }
 //! ```
 
-#![doc(html_root_url = "http://alexcrichton.com/pkg-config-rs")]
+#![doc(html_root_url = "https://docs.rs/pkg-config/0.3")]
 #![cfg_attr(test, deny(warnings))]
 
 use std::ascii::AsciiExt;
 use std::env;
 use std::error;
 use std::ffi::{OsStr, OsString};
 use std::fmt;
 use std::fs;
@@ -77,16 +88,17 @@ pub fn target_supported() -> bool {
 }
 
 #[derive(Clone)]
 pub struct Config {
     statik: Option<bool>,
     atleast_version: Option<String>,
     extra_args: Vec<OsString>,
     cargo_metadata: bool,
+    print_system_libs: bool,
 }
 
 #[derive(Debug)]
 pub struct Library {
     pub libs: Vec<String>,
     pub link_paths: Vec<PathBuf>,
     pub frameworks: Vec<String>,
     pub framework_paths: Vec<PathBuf>,
@@ -102,16 +114,19 @@ pub enum Error {
     /// Contains the name of the responsible environment variable.
     EnvNoPkgConfig(String),
 
     /// Cross compilation detected.
     ///
     /// Override with `PKG_CONFIG_ALLOW_CROSS=1`.
     CrossCompilation,
 
+    /// Attempted to compile using the MSVC ABI build
+    MSVC,
+
     /// Failed to run `pkg-config`.
     ///
     /// Contains the command and the cause.
     Command { command: String, cause: io::Error },
 
     /// `pkg-config` did not exit sucessfully.
     ///
     /// Contains the command and output.
@@ -125,16 +140,17 @@ pub enum Error {
 impl error::Error for Error {
     fn description(&self) -> &str {
         match *self {
             Error::EnvNoPkgConfig(_) => "pkg-config requested to be aborted",
             Error::CrossCompilation => {
                 "pkg-config doesn't handle cross compilation. \
                  Use PKG_CONFIG_ALLOW_CROSS=1 to override"
             }
+            Error::MSVC => "pkg-config is incompatible with the MSVC ABI build.",
             Error::Command { .. } => "failed to run pkg-config",
             Error::Failure { .. } => "pkg-config did not exit sucessfully",
             Error::__Nonexhaustive => panic!(),
         }
     }
 
     fn cause(&self) -> Option<&error::Error> {
         match *self {
@@ -175,16 +191,17 @@ impl fmt::Debug for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         match *self {
             Error::EnvNoPkgConfig(ref name) => {
                 f.debug_tuple("EnvNoPkgConfig")
                  .field(name)
                  .finish()
             }
             Error::CrossCompilation => write!(f, "CrossCompilation"),
+            Error::MSVC => write!(f, "MSVC"),
             Error::Command { ref command, ref cause } => {
                 f.debug_struct("Command")
                  .field("command", command)
                  .field("cause", cause)
                  .finish()
             }
             Error::Failure { ref command, ref output } => {
                 f.debug_struct("Failure")
@@ -202,28 +219,32 @@ impl fmt::Display for Error {
         match *self {
             Error::EnvNoPkgConfig(ref name) => {
                 write!(f, "Aborted because {} is set", name)
             }
             Error::CrossCompilation => {
                 write!(f, "Cross compilation detected. \
                        Use PKG_CONFIG_ALLOW_CROSS=1 to override")
             }
+            Error::MSVC => {
+                write!(f, "MSVC target detected. If you are using the MSVC ABI \
+                       rust build, please use the GNU ABI build instead.")
+            }
             Error::Command { ref command, ref cause } => {
                 write!(f, "Failed to run `{}`: {}", command, cause)
             }
             Error::Failure { ref command, ref output } => {
                 let stdout = str::from_utf8(&output.stdout).unwrap();
                 let stderr = str::from_utf8(&output.stderr).unwrap();
                 try!(write!(f, "`{}` did not exit successfully: {}", command, output.status));
                 if !stdout.is_empty() {
                     try!(write!(f, "\n--- stdout\n{}", stdout));
                 }
                 if !stderr.is_empty() {
-                    try!(write!(f, "\n--- stdout\n{}", stderr));
+                    try!(write!(f, "\n--- stderr\n{}", stderr));
                 }
                 Ok(())
             }
             Error::__Nonexhaustive => panic!(),
         }
     }
 }
 
@@ -249,16 +270,17 @@ pub fn get_variable(package: &str, varia
 impl Config {
     /// Creates a new set of configuration options which are all initially set
     /// to "blank".
     pub fn new() -> Config {
         Config {
             statik: None,
             atleast_version: None,
             extra_args: vec![],
+            print_system_libs: true,
             cargo_metadata: true,
         }
     }
 
     /// Indicate whether the `--static` flag should be passed.
     ///
     /// This will override the inference from environment variables described in
     /// the crate documentation.
@@ -283,32 +305,46 @@ impl Config {
 
     /// Define whether metadata should be emitted for cargo allowing it to
     /// automatically link the binary. Defaults to `true`.
     pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Config {
         self.cargo_metadata = cargo_metadata;
         self
     }
 
+    /// Enable or disable the `PKG_CONFIG_ALLOW_SYSTEM_LIBS` environment
+    /// variable.
+    ///
+    /// This env var is enabled by default.
+    pub fn print_system_libs(&mut self, print: bool) -> &mut Config {
+        self.print_system_libs = print;
+        self
+    }
+
     /// Deprecated in favor fo the `probe` function
     #[doc(hidden)]
     pub fn find(&self, name: &str) -> Result<Library, String> {
         self.probe(name).map_err(|e| e.to_string())
     }
 
     /// Run `pkg-config` to find the library `name`.
     ///
     /// This will use all configuration previously set to specify how
     /// `pkg-config` is run.
     pub fn probe(&self, name: &str) -> Result<Library, Error> {
         let abort_var_name = format!("{}_NO_PKG_CONFIG", envify(name));
         if env::var_os(&abort_var_name).is_some() {
             return Err(Error::EnvNoPkgConfig(abort_var_name))
         } else if !target_supported() {
-            return Err(Error::CrossCompilation);
+            if env::var("TARGET").unwrap_or(String::new()).contains("msvc") {
+                return Err(Error::MSVC);
+            }
+            else {
+                return Err(Error::CrossCompilation);
+            }
         }
 
         let mut library = Library::new();
 
         let output = try!(run(self.command(name, &["--libs", "--cflags"])));
         library.parse_libs_cflags(name, &output, self);
 
         let output = try!(run(self.command(name, &["--modversion"])));
@@ -329,18 +365,21 @@ impl Config {
 
     fn command(&self, name: &str, args: &[&str]) -> Command {
         let exe = env::var("PKG_CONFIG").unwrap_or(String::from("pkg-config"));
         let mut cmd = Command::new(exe);
         if self.is_static(name) {
             cmd.arg("--static");
         }
         cmd.args(args)
-           .args(&self.extra_args)
-           .env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
+           .args(&self.extra_args);
+
+        if self.print_system_libs {
+            cmd.env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
+        }
         if let Some(ref version) = self.atleast_version {
             cmd.arg(&format!("{} >= {}", name, version));
         } else {
             cmd.arg(name);
         }
         cmd
     }
 
--- a/third_party/rust/pkg-config/tests/test.rs
+++ b/third_party/rust/pkg-config/tests/test.rs
@@ -1,18 +1,20 @@
-#![feature(static_mutex)]
-
 extern crate pkg_config;
+#[macro_use]
+extern crate lazy_static;
 
 use pkg_config::Error;
 use std::env;
-use std::sync::{StaticMutex, MUTEX_INIT};
+use std::sync::Mutex;
 use std::path::PathBuf;
 
-static LOCK: StaticMutex = MUTEX_INIT;
+lazy_static! {
+    static ref LOCK: Mutex<()> = Mutex::new(());
+}
 
 fn reset() {
     for (k, _) in env::vars() {
         if k.contains("DYNAMIC") ||
            k.contains("STATIC") ||
            k.contains("PKG_CONFIG_ALLOW_CROSS") ||
            k.contains("FOO_NO_PKG_CONFIG") {
             env::remove_var(&k);
--- a/third_party/rust/quote/.cargo-checksum.json
+++ b/third_party/rust/quote/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"ea9f9bb37492e62dbd04d7a38da935c4ca54b7cc74fb46ed7f99e07116a6966b","src/ident.rs":"830077b64dce8c8ede1fb6ab664cae72f5496f4ab6be21a5b4e3b5e4e57ec425","src/lib.rs":"f799c898057a4e8e1620b32c70e13d3fee7af3a0352a5a4a1da6393942d21cc7","src/to_tokens.rs":"9443c192caa28f1e7d9de80a2d37c87fedd1d8664915513db9ca02a1ee8abfdc","src/tokens.rs":"a559a56905debae32a0e7852114812cca7173341a62b277894517264a759dfa6"},"package":"48f961356de2df29263e751df9e2e2493bd765e57fce250cc8b8dcef53ed33c0"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"a5da41e07bf2d8af3fda684c7adb912e98047e9fe12a8288be3d9e3a494388ca","src/ident.rs":"830077b64dce8c8ede1fb6ab664cae72f5496f4ab6be21a5b4e3b5e4e57ec425","src/lib.rs":"f799c898057a4e8e1620b32c70e13d3fee7af3a0352a5a4a1da6393942d21cc7","src/to_tokens.rs":"a871cb84506fa9e0783ac29617d686327ce5d05a9711a3a10833430b00345ccc","src/tokens.rs":"a559a56905debae32a0e7852114812cca7173341a62b277894517264a759dfa6"},"package":"e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"}
\ No newline at end of file
--- a/third_party/rust/quote/Cargo.toml
+++ b/third_party/rust/quote/Cargo.toml
@@ -1,10 +1,10 @@
 [package]
 name = "quote"
-version = "0.3.11" # don't forget to update version in readme for breaking changes
+version = "0.3.12" # don't forget to update version in readme for breaking changes
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Quasi-quoting macro quote!(...)"
 repository = "https://github.com/dtolnay/quote"
 documentation = "https://docs.rs/quote/"
 keywords = ["syn"]
 include = ["Cargo.toml", "src/**/*.rs"]
--- a/third_party/rust/quote/src/to_tokens.rs
+++ b/third_party/rust/quote/src/to_tokens.rs
@@ -1,10 +1,12 @@
 use super::Tokens;
 
+use std::borrow::Cow;
+
 /// Types that can be interpolated inside a `quote!(...)` invocation.
 pub trait ToTokens {
     /// Write `self` to the given `Tokens`.
     ///
     /// Example implementation for a struct representing Rust paths like
     /// `std::cmp::PartialEq`:
     ///
     /// ```ignore
@@ -28,16 +30,22 @@ pub trait ToTokens {
 }
 
 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
     fn to_tokens(&self, tokens: &mut Tokens) {
         (**self).to_tokens(tokens);
     }
 }
 
+impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        (**self).to_tokens(tokens);
+    }
+}
+
 impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
     fn to_tokens(&self, tokens: &mut Tokens) {
         (**self).to_tokens(tokens);
     }
 }
 
 impl<T: ToTokens> ToTokens for Option<T> {
     fn to_tokens(&self, tokens: &mut Tokens) {
--- a/third_party/rust/serde/.cargo-checksum.json
+++ b/third_party/rust/serde/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"3044d8bcb7afe720659ce9a00f0c1eb6affbd6d5134da7cf41e02b8a6976fd64","src/bytes.rs":"ec2fb40df6a1e1233462d85145a57eb33a1df0140ed921e9fe0a0ca35c7c1064","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"3e27049398fc000ae0ec89f0358e5cd8fe55d6ddf0bc5a0a9ae9de936ce0935b","src/de/mod.rs":"62291b6b7c29d411b9ff212cab480982e535e7aee21c1729b4bb592d681ab807","src/de/value.rs":"6dd878ce762799048c0ebc8f834932871e1bdf24953ea69415a2b2148e0d3dbc","src/error.rs":"da31d3881930f0e787d75191984f71fe2e1419d9331c68baa0fc0ce2d561766b","src/iter.rs":"30090fe6ab49bb1d8c7fec362cace52981b2c4e1a1a8e3fad4117eab558cdde6","src/lib.rs":"67f62df097e3b55a90a566af56d6e3c641f719300db8bfd5603ed5a2bff1aa8e","src/macros.rs":"e81e421815fac10d6a7bfb727bbe7b4f24e99b03cd8739efc806e4b704ac7b4e","src/ser/impls.rs":"36d372af1dae11444f85e497eefb98449bae70260348cdfb098c508439be7952","src/ser/mod.rs":"626e8ef5b1ddaf00fe84905e936046c40217e31609d5a56ca658f4eb23983fd5","src/utils.rs":"b0d1a54af90e3620abd66479d757a2eb442449788c4ece93161916da0838affa"},"package":"f1e4aab5b62fb90ac9c99d5a55caa7c37e06a15d1b189ccc2b117782655fd11f"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"37cf6256c6eb377c59bac3c48ca9ac70b100173c1114de357084edf2a5381044","src/bytes.rs":"ec2fb40df6a1e1233462d85145a57eb33a1df0140ed921e9fe0a0ca35c7c1064","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"3e27049398fc000ae0ec89f0358e5cd8fe55d6ddf0bc5a0a9ae9de936ce0935b","src/de/mod.rs":"62291b6b7c29d411b9ff212cab480982e535e7aee21c1729b4bb592d681ab807","src/de/value.rs":"6dd878ce762799048c0ebc8f834932871e1bdf24953ea69415a2b2148e0d3dbc","src/error.rs":"da31d3881930f0e787d75191984f71fe2e1419d9331c68baa0fc0ce2d561766b","src/iter.rs":"30090fe6ab49bb1d8c7fec362cace52981b2c4e1a1a8e3fad4117eab558cdde6","src/lib.rs":"67f62df097e3b55a90a566af56d6e3c641f719300db8bfd5603ed5a2bff1aa8e","src/macros.rs":"e81e421815fac10d6a7bfb727bbe7b4f24e99b03cd8739efc806e4b704ac7b4e","src/ser/impls.rs":"36d372af1dae11444f85e497eefb98449bae70260348cdfb098c508439be7952","src/ser/mod.rs":"626e8ef5b1ddaf00fe84905e936046c40217e31609d5a56ca658f4eb23983fd5","src/utils.rs":"b0d1a54af90e3620abd66479d757a2eb442449788c4ece93161916da0838affa"},"package":"9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"}
\ No newline at end of file
--- a/third_party/rust/serde/Cargo.toml
+++ b/third_party/rust/serde/Cargo.toml
@@ -1,19 +1,20 @@
 [package]
 name = "serde"
-version = "0.8.22"
+version = "0.8.23"
 authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "A generic serialization/deserialization framework"
 homepage = "https://serde.rs"
 repository = "https://github.com/serde-rs/serde"
 documentation = "https://docs.serde.rs/serde/"
 readme = "../README.md"
 keywords = ["serde", "serialization"]
+categories = ["encoding"]
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [features]
 default = ["std"]
 
 std = []
 unstable = []
 alloc = ["unstable"]
--- a/third_party/rust/serde_codegen/.cargo-checksum.json
+++ b/third_party/rust/serde_codegen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"bfe45d3c81652b67353686fcf8c93d85f32f025d0f379d74b43abd50fe1688ca","src/bound.rs":"d1f94299052acaeeae0c011c2304b072dec76c7c32469d2b8881c2e380346496","src/de.rs":"a16c27918c973463427faaa98a7e7bd156c828bac4b96d605c30f82dad347476","src/lib.rs":"3ce6c8c8445b9f0987472477586c26281dd129f7dd9af4fd0a99d51bdfb65782","src/ser.rs":"5b86cf6b0b7941d3d82f3ed32cd26b845c821558f086fe9d7237f0ff1e066e61"},"package":"200c97dd86298518356c694869a7a51af1de398bd6c6dcce89fa21a512fdea44"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"b16e3c93d139c09eb72a661a4201661c3c57ccca250a928a2ebc29f587d92540","src/bound.rs":"d1f94299052acaeeae0c011c2304b072dec76c7c32469d2b8881c2e380346496","src/de.rs":"a16c27918c973463427faaa98a7e7bd156c828bac4b96d605c30f82dad347476","src/lib.rs":"3ce6c8c8445b9f0987472477586c26281dd129f7dd9af4fd0a99d51bdfb65782","src/ser.rs":"5b86cf6b0b7941d3d82f3ed32cd26b845c821558f086fe9d7237f0ff1e066e61"},"package":"a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc"}
\ No newline at end of file
--- a/third_party/rust/serde_codegen/Cargo.toml
+++ b/third_party/rust/serde_codegen/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "serde_codegen"
-version = "0.8.22"
+version = "0.8.23"
 authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Macros to auto-generate implementations for the serde framework"
 homepage = "https://serde.rs"
 repository = "https://github.com/serde-rs/serde"
 documentation = "https://serde.rs/codegen.html"
 keywords = ["serde", "serialization"]
 include = ["Cargo.toml", "src/**/*.rs"]
--- a/third_party/rust/syn/.cargo-checksum.json
+++ b/third_party/rust/syn/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"a65b38a99a6385032b3f2d35684fcffe4bb54fb4e402e9aa7aa002c0cff29a59","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"d83f4c1a48e3580caa028cfabde6ace232efc95d70af6dc9cfcca48317db9ad7","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"885c94b29ab8ee45c72a682221e241d1f0dd09c659809fe77279b5dd8a4bc645","src/aster/ty.rs":"90649aad98617c09ffc43a38aeb823a3298c41bf5e10f0ef3500b71c81021c2f","src/aster/ty_param.rs":"7ced1e6ca0c98ef468d507d3f07bfcb1171395cd66ff5c3e1b091fe7e8b9a562","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"2ba436bdd439511be10baf9ad45226ade678176a7fd45a087367e1ad2b43e07a","src/constant.rs":"90535a2320e0dc8ab623a9bffa770bdf697baef2884a7d9224b31daf422ea5a0","src/data.rs":"0119c67821f846e67d792bea638ae7f7f5d7e2f5e5a0c145d8ba8766d6ddb0f9","src/escape.rs":"e035b1f6ce3255e868fddb62ee90a95a2f3caf2db73786a2b179b92e9e337539","src/expr.rs":"02e8d346bef099974d06d74945be92fe6391111b94154df4981d44f1594d5579","src/generics.rs":"a300acff4c6e61d2fe9344db23f5e176e7abb02529bc348d9180f41ad0a4caf6","src/helper.rs":"9693d5c78f2d627a90d689a5d4bee1061eddcb646ae6dff3b2e4fd7cfbb33845","src/ident.rs":"83142b0107baba3137aad3b7d5c7b468ab53bf837bd9544d117d6644080d2705","src/item.rs":"63f2cd9a01c279405196d90a7d1cc530896157352163fb44f6b2a713657058b8","src/krate.rs":"324073a42389eb1c26a9d0f325b4f1cdd37d00a9bcaf07fdee77af54909a452d","src/lib.rs":"ef584db9ac9b7308224798d3983cbf201df7f0da1735fe5ce408f20fb3df763e","src/lit.rs":"2615fc6041f11b67a7cd62012f36eb215fd1fdf6649b6b64d728625148f53c7b","src/mac.rs":"45c44bd7abcbdaea6572bb4721bdc57b02b967ea9865172fe10e029e51e51a42","src/macro_input.rs":"93b999877879076e1f47502d96aa18aad82117d072044ca9de825c8a9bfa60b8","src/nom.rs":"642149bf322b762e02183ac1fed641df7f03ac53334c869a64707de4e9c5e68c","src/op.rs":"232f84ba605ed50e70ee02169dd551548872135cf56f155637917ec3bf810ce1","src/registry.rs":"b709f2a0f372efd8dec8fd46d6d71fb3b56a0261789e6de048a41a5e70144421","src/space.rs":"de9cb71e831c1d66f0bf2f3f219c3455d1979ca89f89b198d3b324e0cd50faf8","src/ty.rs":"97cfcb904a5fd68a42ebd2e5f86466d92e0785b1491d80c2a8d396ccec1b742a","src/visit.rs":"d7dcf429cc1a05821a66a4b38e7856eec45a9b2215f625d95030c3688eda26ca"},"package":"17134635792e6a2361f53efbee798701796d8b5842c1c21b7cdb875e2950c8fc"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c1650ed29ad7cb01e5da2e0efd299062cd38272d0dc971f8f8f5979a0aaadd4c","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"d83f4c1a48e3580caa028cfabde6ace232efc95d70af6dc9cfcca48317db9ad7","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"885c94b29ab8ee45c72a682221e241d1f0dd09c659809fe77279b5dd8a4bc645","src/aster/ty.rs":"90649aad98617c09ffc43a38aeb823a3298c41bf5e10f0ef3500b71c81021c2f","src/aster/ty_param.rs":"7ced1e6ca0c98ef468d507d3f07bfcb1171395cd66ff5c3e1b091fe7e8b9a562","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"2ba436bdd439511be10baf9ad45226ade678176a7fd45a087367e1ad2b43e07a","src/constant.rs":"90535a2320e0dc8ab623a9bffa770bdf697baef2884a7d9224b31daf422ea5a0","src/data.rs":"0119c67821f846e67d792bea638ae7f7f5d7e2f5e5a0c145d8ba8766d6ddb0f9","src/escape.rs":"e035b1f6ce3255e868fddb62ee90a95a2f3caf2db73786a2b179b92e9e337539","src/expr.rs":"1e8b194f213e3279c0cb414f450ebab78c657951b8c2abf97378e745467ca8f5","src/generics.rs":"a300acff4c6e61d2fe9344db23f5e176e7abb02529bc348d9180f41ad0a4caf6","src/helper.rs":"9693d5c78f2d627a90d689a5d4bee1061eddcb646ae6dff3b2e4fd7cfbb33845","src/ident.rs":"83142b0107baba3137aad3b7d5c7b468ab53bf837bd9544d117d6644080d2705","src/item.rs":"5f7ba91d7642612ddaba9e862695234f4fdda88009f83ad5dee8ac6180a4f08d","src/krate.rs":"324073a42389eb1c26a9d0f325b4f1cdd37d00a9bcaf07fdee77af54909a452d","src/lib.rs":"2e1c12a937ed5c0f80620f4166463fed8119f0620c2b984ccd484b30ed3ee71c","src/lit.rs":"2615fc6041f11b67a7cd62012f36eb215fd1fdf6649b6b64d728625148f53c7b","src/mac.rs":"b7f7f67f6e7830b9dc2fd7fb4996c6821937687c44d2fbdc34ecc89e43815eff","src/macro_input.rs":"93b999877879076e1f47502d96aa18aad82117d072044ca9de825c8a9bfa60b8","src/nom.rs":"e877f3492633186e6499775c9bfa58c2554c25d8a6467ee1567d13706386b4c3","src/op.rs":"232f84ba605ed50e70ee02169dd551548872135cf56f155637917ec3bf810ce1","src/registry.rs":"b709f2a0f372efd8dec8fd46d6d71fb3b56a0261789e6de048a41a5e70144421","src/space.rs":"de9cb71e831c1d66f0bf2f3f219c3455d1979ca89f89b198d3b324e0cd50faf8","src/ty.rs":"d5562321530c739d7b25324463a94f685837824333ec7d604aefbd782f9ec2fb","src/visit.rs":"d3133ff25aa9cc8e6ec15f579bfa753a264518b0a7de2f2be4586d49632a9aac"},"package":"e5aaf7e4a0f90d7285445c881dcc28f1a510e4962b4ffcdde17f5775b2960df6"}
\ No newline at end of file
--- a/third_party/rust/syn/Cargo.toml
+++ b/third_party/rust/syn/Cargo.toml
@@ -1,32 +1,33 @@
 [package]
 name = "syn"
-version = "0.10.6" # don't forget to update version in readme for breaking changes
+version = "0.10.7" # don't forget to update version in readme for breaking changes
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Nom parser for Rust source code"
 repository = "https://github.com/dtolnay/syn"
 documentation = "https://dtolnay.github.io/syn/syn/"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [features]
 default = ["parsing", "printing"]
 aster = []
 expand = ["full", "parsing", "printing"]
-full = []
+full = ["type-macros"]
 parsing = ["unicode-xid"]
 pretty = ["syntex_syntax"]
 printing = ["quote"]
+type-macros = []
 visit = []
 
 [dependencies]
 clippy = { version = "0.*", optional = true }
 quote = { version = "0.3.0", optional = true }
-syntex_syntax = { version = "0.50.0", optional = true }
-unicode-xid = { version = "0.0.3", optional = true }
+syntex_syntax = { version = "0.52.0", optional = true }
+unicode-xid = { version = "0.0.4", optional = true }
 
 [dev-dependencies]
-syntex_pos = "0.50.0"
-syntex_syntax = "0.50.0"
+syntex_pos = "0.52.0"
+syntex_syntax = "0.52.0"
 tempdir = "0.3.5"
 time = "0.1.35"
 walkdir = "1.0.1"
--- a/third_party/rust/syn/src/expr.rs
+++ b/third_party/rust/syn/src/expr.rs
@@ -80,20 +80,20 @@ pub enum ExprKind {
     /// This is desugared to a combination of `loop` and `match` expressions.
     ForLoop(Box<Pat>, Box<Expr>, Block, Option<Ident>),
     /// Conditionless loop (can be exited with break, continue, or return)
     ///
     /// `'label: loop { block }`
     Loop(Block, Option<Ident>),
     /// A `match` block.
     Match(Box<Expr>, Vec<Arm>),
-    /// A closure (for example, `move |a, b, c| {a + b + c}`)
-    Closure(CaptureBy, Box<FnDecl>, Block),
+    /// A closure (for example, `move |a, b, c| a + b + c`)
+    Closure(CaptureBy, Box<FnDecl>, Box<Expr>),
     /// A block (`{ ... }` or `unsafe { ... }`)
-    Block(BlockCheckMode, Block),
+    Block(Unsafety, Block),
 
     /// An assignment (`a = foo()`)
     Assign(Box<Expr>, Box<Expr>),
     /// An assignment with an operator
     ///
     /// For example, `a += 1`.
     AssignOp(BinOp, Box<Expr>, Box<Expr>),
     /// Access of a named struct field (`obj.foo`)
@@ -111,18 +111,18 @@ pub enum ExprKind {
     /// parameters, e.g. foo::bar::<baz>.
     ///
     /// Optionally "qualified",
     /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
     Path(Option<QSelf>, Path),
 
     /// A referencing operation (`&a` or `&mut a`)
     AddrOf(Mutability, Box<Expr>),
-    /// A `break`, with an optional label to break
-    Break(Option<Ident>),
+    /// A `break`, with an optional label to break, and an optional expression
+    Break(Option<Ident>, Option<Box<Expr>>),
     /// A `continue`, with an optional label
     Continue(Option<Ident>),
     /// A `return`, with an optional value to be returned
     Ret(Option<Box<Expr>>),
 
     /// A macro invocation; pre-expansion
     Mac(Mac),
 
@@ -156,22 +156,16 @@ pub struct FieldValue {
 ///
 /// E.g. `{ .. }` as in `fn foo() { .. }`
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct Block {
     /// Statements in a block
     pub stmts: Vec<Stmt>,
 }
 
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum BlockCheckMode {
-    Default,
-    Unsafe,
-}
-
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub enum Stmt {
     /// A local (let) binding.
     Local(Box<Local>),
 
     /// An item definition.
     Item(Box<Item>),
 
@@ -307,26 +301,26 @@ pub enum BindingMode {
     ByRef(Mutability),
     ByValue(Mutability),
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, Mac,
-         TokenTree, Ty, UnOp};
+         TokenTree, Ty, UnOp, Unsafety};
     use attr::parsing::outer_attr;
     use generics::parsing::lifetime;
     use ident::parsing::{ident, wordlike};
     use item::parsing::item;
     use lit::parsing::{digits, lit};
     use mac::parsing::{mac, token_trees};
     use nom::IResult::{self, Error};
     use op::parsing::{assign_op, binop, unop};
-    use ty::parsing::{mutability, path, qpath, ty};
+    use ty::parsing::{mutability, path, qpath, ty, unsafety};
 
     // Struct literals are ambiguous in certain positions
     // https://github.com/rust-lang/rfcs/pull/92
     macro_rules! named_ambiguous_expr {
         ($name:ident -> $o:ty, $allow_struct:ident, $submac:ident!( $($args:tt)* )) => {
             fn $name(i: &str, $allow_struct: bool) -> $crate::nom::IResult<&str, $o> {
                 $submac!(i, $($args)*)
             }
@@ -350,17 +344,17 @@ pub mod parsing {
                 expr_lit // must be before expr_struct
                 |
                 cond_reduce!(allow_struct, expr_struct) // must be before expr_path
                 |
                 expr_paren // must be before expr_tup
                 |
                 expr_mac // must be before expr_path
                 |
-                expr_break // must be before expr_path
+                call!(expr_break, allow_struct) // must be before expr_path
                 |
                 expr_continue // must be before expr_path
                 |
                 call!(expr_ret, allow_struct) // must be before expr_path
                 |
                 call!(expr_box, allow_struct)
                 |
                 expr_in_place
@@ -469,17 +463,17 @@ pub mod parsing {
     named!(expr_in_place -> ExprKind, do_parse!(
         keyword!("in") >>
         place: expr_no_struct >>
         punct!("{") >>
         value: within_block >>
         punct!("}") >>
         (ExprKind::InPlace(
             Box::new(place),
-            Box::new(ExprKind::Block(BlockCheckMode::Default, Block {
+            Box::new(ExprKind::Block(Unsafety::Normal, Block {
                 stmts: value,
             }).into()),
         ))
     ));
 
     named!(expr_vec -> ExprKind, do_parse!(
         punct!("[") >>
         elems: terminated_list!(punct!(","), expr) >>
@@ -566,17 +560,17 @@ pub mod parsing {
             keyword!("else"),
             alt!(
                 expr_if
                 |
                 do_parse!(
                     punct!("{") >>
                     else_block: within_block >>
                     punct!("}") >>
-                    (ExprKind::Block(BlockCheckMode::Default, Block {
+                    (ExprKind::Block(Unsafety::Normal, Block {
                         stmts: else_block,
                     }).into())
                 )
             )
         )) >>
         (match cond {
             Cond::Let(pat, expr) => ExprKind::IfLet(
                 Box::new(pat),
@@ -627,30 +621,30 @@ pub mod parsing {
         punct!("}") >>
         (ExprKind::Match(Box::new(obj), {
             arms.extend(last_arm);
             arms
         }))
     ));
 
     fn arm_requires_comma(arm: &Arm) -> bool {
-        if let ExprKind::Block(BlockCheckMode::Default, _) = arm.body.node {
+        if let ExprKind::Block(Unsafety::Normal, _) = arm.body.node {
             false
         } else {
             true
         }
     }
 
     named!(match_arm -> Arm, do_parse!(
         attrs: many0!(outer_attr) >>
         pats: separated_nonempty_list!(punct!("|"), pat) >>
         guard: option!(preceded!(keyword!("if"), expr)) >>
         punct!("=>") >>
         body: alt!(
-            map!(block, |blk| ExprKind::Block(BlockCheckMode::Default, blk).into())
+            map!(block, |blk| ExprKind::Block(Unsafety::Normal, blk).into())
             |
             expr
         ) >>
         (Arm {
             attrs: attrs,
             pats: pats,
             guard: guard.map(Box::new),
             body: Box::new(body),
@@ -662,34 +656,29 @@ pub mod parsing {
         punct!("|") >>
         inputs: terminated_list!(punct!(","), closure_arg) >>
         punct!("|") >>
         ret_and_body: alt!(
             do_parse!(
                 punct!("->") >>
                 ty: ty >>
                 body: block >>
-                ((FunctionRetTy::Ty(ty), body))
+                (FunctionRetTy::Ty(ty), ExprKind::Block(Unsafety::Normal, body).into())
             )
             |
-            map!(ambiguous_expr!(allow_struct), |e| (
-                FunctionRetTy::Default,
-                Block {
-                    stmts: vec![Stmt::Expr(Box::new(e))],
-                },
-            ))
+            map!(ambiguous_expr!(allow_struct), |e| (FunctionRetTy::Default, e))
         ) >>
         (ExprKind::Closure(
             capture,
             Box::new(FnDecl {
                 inputs: inputs,
                 output: ret_and_body.0,
                 variadic: false,
             }),
-            ret_and_body.1,
+            Box::new(ret_and_body.1),
         ))
     ));
 
     named!(closure_arg -> FnArg, do_parse!(
         pat: pat >>
         ty: option!(preceded!(punct!(":"), ty)) >>
         (FnArg::Captured(pat, ty.unwrap_or(Ty::Infer)))
     ));
@@ -715,20 +704,21 @@ pub mod parsing {
     ));
 
     named!(expr_continue -> ExprKind, do_parse!(
         keyword!("continue") >>
         lbl: option!(label) >>
         (ExprKind::Continue(lbl))
     ));
 
-    named!(expr_break -> ExprKind, do_parse!(
+    named_ambiguous_expr!(expr_break -> ExprKind, allow_struct, do_parse!(
         keyword!("break") >>
         lbl: option!(label) >>
-        (ExprKind::Break(lbl))
+        val: option!(call!(ambiguous_expr, allow_struct, false)) >>
+        (ExprKind::Break(lbl, val.map(Box::new)))
     ));
 
     named_ambiguous_expr!(expr_ret -> ExprKind, allow_struct, do_parse!(
         keyword!("return") >>
         ret_value: option!(ambiguous_expr!(allow_struct)) >>
         (ExprKind::Ret(ret_value.map(Box::new)))
     ));
 
@@ -771,17 +761,17 @@ pub mod parsing {
         value: expr >>
         punct!(";") >>
         times: expr >>
         punct!("]") >>
         (ExprKind::Repeat(Box::new(value), Box::new(times)))
     ));
 
     named!(expr_block -> ExprKind, do_parse!(
-        rules: block_check_mode >>
+        rules: unsafety >>
         b: block >>
         (ExprKind::Block(rules, Block {
             stmts: b.stmts,
         }))
     ));
 
     named_ambiguous_expr!(expr_range -> ExprKind, allow_struct, do_parse!(
         limits: range_limits >>
@@ -829,22 +819,16 @@ pub mod parsing {
         punct!("{") >>
         stmts: within_block >>
         punct!("}") >>
         (Block {
             stmts: stmts,
         })
     ));
 
-    named!(block_check_mode -> BlockCheckMode, alt!(
-        keyword!("unsafe") => { |_| BlockCheckMode::Unsafe }
-        |
-        epsilon!() => { |_| BlockCheckMode::Default }
-    ));
-
     named!(pub within_block -> Vec<Stmt>, do_parse!(
         many0!(punct!(";")) >>
         mut standalone: many0!(terminated!(standalone_stmt, many0!(punct!(";")))) >>
         last: option!(expr) >>
         (match last {
             None => standalone,
             Some(last) => {
                 standalone.push(Stmt::Expr(Box::new(last)));
@@ -860,27 +844,27 @@ pub mod parsing {
         |
         stmt_item
         |
         stmt_expr
     ));
 
     named!(stmt_mac -> Stmt, do_parse!(
         attrs: many0!(outer_attr) >>
-        name: ident >>
+        what: path >>
         punct!("!") >>
     // Only parse braces here; paren and bracket will get parsed as
     // expression statements
         punct!("{") >>
         tts: token_trees >>
         punct!("}") >>
         semi: option!(punct!(";")) >>
         (Stmt::Mac(Box::new((
             Mac {
-                path: name.into(),
+                path: what,
                 tts: vec![TokenTree::Delimited(Delimited {
                     delim: DelimToken::Brace,
                     tts: tts,
                 })],
             },
             if semi.is_some() {
                 MacStmtStyle::Semicolon
             } else {
@@ -1154,17 +1138,17 @@ pub mod parsing {
     ));
 
     named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    use {FnArg, FunctionRetTy, Mutability, Ty};
+    use {FnArg, FunctionRetTy, Mutability, Ty, Unsafety};
     use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Expr {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
             match self.node {
                 ExprKind::Box(ref inner) => {
@@ -1292,49 +1276,39 @@ mod printing {
                 }
                 ExprKind::Match(ref expr, ref arms) => {
                     tokens.append("match");
                     expr.to_tokens(tokens);
                     tokens.append("{");
                     tokens.append_all(arms);
                     tokens.append("}");
                 }
-                ExprKind::Closure(capture, ref decl, ref body) => {
+                ExprKind::Closure(capture, ref decl, ref expr) => {
                     capture.to_tokens(tokens);
                     tokens.append("|");
                     for (i, input) in decl.inputs.iter().enumerate() {
                         if i > 0 {
                             tokens.append(",");
                         }
                         match *input {
                             FnArg::Captured(ref pat, Ty::Infer) => {
                                 pat.to_tokens(tokens);
                             }
                             _ => input.to_tokens(tokens),
                         }
                     }
                     tokens.append("|");
                     match decl.output {
-                        FunctionRetTy::Default => {
-                            if body.stmts.len() == 1 {
-                                if let Stmt::Expr(ref expr) = body.stmts[0] {
-                                    expr.to_tokens(tokens);
-                                } else {
-                                    body.to_tokens(tokens);
-                                }
-                            } else {
-                                body.to_tokens(tokens);
-                            }
-                        }
+                        FunctionRetTy::Default => { /* nothing */ }
                         FunctionRetTy::Ty(ref ty) => {
                             tokens.append("->");
                             ty.to_tokens(tokens);
-                            body.to_tokens(tokens);
                         }
                     }
+                    expr.to_tokens(tokens);
                 }
                 ExprKind::Block(rules, ref block) => {
                     rules.to_tokens(tokens);
                     block.to_tokens(tokens);
                 }
                 ExprKind::Assign(ref var, ref expr) => {
                     var.to_tokens(tokens);
                     tokens.append("=");
@@ -1391,19 +1365,20 @@ mod printing {
                         segment.to_tokens(tokens);
                     }
                 }
                 ExprKind::AddrOf(mutability, ref expr) => {
                     tokens.append("&");
                     mutability.to_tokens(tokens);
                     expr.to_tokens(tokens);
                 }
-                ExprKind::Break(ref opt_label) => {
+                ExprKind::Break(ref opt_label, ref opt_val) => {
                     tokens.append("break");
                     opt_label.to_tokens(tokens);
+                    opt_val.to_tokens(tokens);
                 }
                 ExprKind::Continue(ref opt_label) => {
                     tokens.append("continue");
                     opt_label.to_tokens(tokens);
                 }
                 ExprKind::Ret(ref opt_expr) => {
                     tokens.append("return");
                     opt_expr.to_tokens(tokens);
@@ -1460,17 +1435,17 @@ mod printing {
             tokens.append_separated(&self.pats, "|");
             if let Some(ref guard) = self.guard {
                 tokens.append("if");
                 guard.to_tokens(tokens);
             }
             tokens.append("=>");
             self.body.to_tokens(tokens);
             match self.body.node {
-                ExprKind::Block(BlockCheckMode::Default, _) => {
+                ExprKind::Block(Unsafety::Normal, _) => {
                     // no comma
                 }
                 _ => tokens.append(","),
             }
         }
     }
 
     impl ToTokens for Pat {
@@ -1641,27 +1616,16 @@ mod printing {
     impl ToTokens for Block {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append("{");
             tokens.append_all(&self.stmts);
             tokens.append("}");
         }
     }
 
-    impl ToTokens for BlockCheckMode {
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
-                BlockCheckMode::Default => {
-                    // nothing
-                }
-                BlockCheckMode::Unsafe => tokens.append("unsafe"),
-            }
-        }
-    }
-
     impl ToTokens for Stmt {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
                 Stmt::Local(ref local) => local.to_tokens(tokens),
                 Stmt::Item(ref item) => item.to_tokens(tokens),
                 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
                 Stmt::Semi(ref expr) => {
                     expr.to_tokens(tokens);
--- a/third_party/rust/syn/src/item.rs
+++ b/third_party/rust/syn/src/item.rs
@@ -275,30 +275,30 @@ pub mod parsing {
         |
         item_mac
     ));
 
     named!(pub items -> Vec<Item>, many0!(item));
 
     named!(item_mac -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
-        path: ident >>
+        what: path >>
         punct!("!") >>
         name: option!(ident) >>
         body: delimited >>
         cond!(match body.delim {
             DelimToken::Paren | DelimToken::Bracket => true,
             DelimToken::Brace => false,
         }, punct!(";")) >>
         (Item {
             ident: name.unwrap_or_else(|| Ident::new("")),
             vis: Visibility::Inherited,
             attrs: attrs,
             node: ItemKind::Mac(Mac {
-                path: path.into(),
+                path: what,
                 tts: vec![TokenTree::Delimited(body)],
             }),
         })
     ));
 
     named!(item_extern_crate -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
@@ -816,28 +816,28 @@ pub mod parsing {
             ident: id,
             attrs: attrs,
             node: TraitItemKind::Type(bounds, default),
         })
     ));
 
     named!(trait_item_mac -> TraitItem, do_parse!(
         attrs: many0!(outer_attr) >>
-        id: ident >>
+        what: path >>
         punct!("!") >>
         body: delimited >>
         cond!(match body.delim {
             DelimToken::Paren | DelimToken::Bracket => true,
             DelimToken::Brace => false,
         }, punct!(";")) >>
         (TraitItem {
-            ident: id.clone(),
+            ident: Ident::new(""),
             attrs: attrs,
             node: TraitItemKind::Macro(Mac {
-                path: id.into(),
+                path: what,
                 tts: vec![TokenTree::Delimited(body)],
             }),
         })
     ));
 
     named!(item_impl -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
         unsafety: unsafety >>
@@ -971,30 +971,30 @@ pub mod parsing {
             defaultness: defaultness,
             attrs: attrs,
             node: ImplItemKind::Type(ty),
         })
     ));
 
     named!(impl_item_macro -> ImplItem, do_parse!(
         attrs: many0!(outer_attr) >>
-        id: ident >>
+        what: path >>
         punct!("!") >>
         body: delimited >>
         cond!(match body.delim {
             DelimToken::Paren | DelimToken::Bracket => true,
             DelimToken::Brace => false,
         }, punct!(";")) >>
         (ImplItem {
-            ident: id.clone(),
+            ident: Ident::new(""),
             vis: Visibility::Inherited,
             defaultness: Defaultness::Final,
             attrs: attrs,
             node: ImplItemKind::Macro(Mac {
-                path: id.into(),
+                path: what,
                 tts: vec![TokenTree::Delimited(body)],
             }),
         })
     ));
 
     named!(impl_polarity -> ImplPolarity, alt!(
         punct!("!") => { |_| ImplPolarity::Negative }
         |
--- a/third_party/rust/syn/src/lib.rs
+++ b/third_party/rust/syn/src/lib.rs
@@ -32,18 +32,18 @@ mod data;
 pub use data::{Field, Variant, VariantData, Visibility};
 
 #[cfg(feature = "parsing")]
 mod escape;
 
 #[cfg(feature = "full")]
 mod expr;
 #[cfg(feature = "full")]
-pub use expr::{Arm, BindingMode, Block, BlockCheckMode, CaptureBy, Expr, ExprKind, FieldPat,
-               FieldValue, Local, MacStmtStyle, Pat, RangeLimits, Stmt};
+pub use expr::{Arm, BindingMode, Block, CaptureBy, Expr, ExprKind, FieldPat, FieldValue,
+               Local, MacStmtStyle, Pat, RangeLimits, Stmt};
 
 mod generics;
 pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
                    WhereBoundPredicate, WhereClause, WherePredicate, WhereRegionPredicate};
 #[cfg(feature = "printing")]
 pub use generics::{ImplGenerics, TyGenerics};
 
 mod ident;
@@ -59,19 +59,19 @@ pub use item::{Constness, Defaultness, F
 #[cfg(feature = "full")]
 mod krate;
 #[cfg(feature = "full")]
 pub use krate::Crate;
 
 mod lit;
 pub use lit::{FloatTy, IntTy, Lit, StrStyle};
 
-#[cfg(feature = "full")]
+#[cfg(feature = "type-macros")]
 mod mac;
-#[cfg(feature = "full")]
+#[cfg(feature = "type-macros")]
 pub use mac::{BinOpToken, DelimToken, Delimited, Mac, Token, TokenTree};
 
 mod macro_input;
 pub use macro_input::{Body, MacroInput};
 
 mod op;
 pub use op::{BinOp, UnOp};
 
--- a/third_party/rust/syn/src/mac.rs
+++ b/third_party/rust/syn/src/mac.rs
@@ -109,26 +109,27 @@ pub enum DelimToken {
     Brace,
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use Lifetime;
     use generics::parsing::lifetime;
-    use ident::parsing::{ident, word};
+    use ident::parsing::word;
     use lit::parsing::lit;
     use space::{block_comment, whitespace};
+    use ty::parsing::path;
 
     named!(pub mac -> Mac, do_parse!(
-        name: ident >>
+        what: path >>
         punct!("!") >>
         body: delimited >>
         (Mac {
-            path: name.into(),
+            path: what,
             tts: vec![TokenTree::Delimited(body)],
         })
     ));
 
     named!(pub token_trees -> Vec<TokenTree>, many0!(token_tree));
 
     named!(pub delimited -> Delimited, alt!(
         delimited!(
--- a/third_party/rust/syn/src/nom.rs
+++ b/third_party/rust/syn/src/nom.rs
@@ -227,32 +227,22 @@ macro_rules! take_while1 {
         }
     }};
 
     ($input:expr, $f:expr) => {
         take_while1!($input, call!($f));
     };
 }
 
-pub fn str_chars(s: &str) -> Vec<char> {
-    // Can't do `s.chars().collect()` because it triggers a compiler bug in 1.12.0
-    // https://github.com/dtolnay/syn/issues/20
-    let mut result = Vec::new();
-    for ch in s.chars() {
-        result.push(ch);
-    }
-    result
-}
-
 macro_rules! take_until {
     ($input:expr, $substr:expr) => {{
         if $substr.len() > $input.len() {
             $crate::nom::IResult::Error
         } else {
-            let substr_vec: Vec<char> = $crate::nom::str_chars($substr);
+            let substr_vec: Vec<char> = $substr.chars().collect();
             let mut window: Vec<char> = vec![];
             let mut offset = $input.len();
             let mut parsed = false;
             for (o, c) in $input.char_indices() {
                 window.push(c);
                 if window.len() > substr_vec.len() {
                     window.remove(0);
                 }
--- a/third_party/rust/syn/src/ty.rs
+++ b/third_party/rust/syn/src/ty.rs
@@ -28,16 +28,24 @@ pub enum Ty {
     PolyTraitRef(Vec<TyParamBound>),
     /// An `impl TraitA+TraitB` type.
     ImplTrait(Vec<TyParamBound>),
     /// No-op; kept solely so that we can pretty-print faithfully
     Paren(Box<Ty>),
     /// TyKind::Infer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     Infer,
+    /// A macro in the type position.
+    Mac(Mac),
+}
+
+#[cfg(not(feature = "type-macros"))]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct Mac {
+    _private: (),
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct MutTy {
     pub ty: Ty,
     pub mutability: Mutability,
 }
 
@@ -50,17 +58,20 @@ pub enum Mutability {
 /// A "Path" is essentially Rust's notion of a name.
 ///
 /// It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
 ///
 /// E.g. `std::cmp::PartialEq`
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct Path {
+    /// A `::foo` path, is relative to the crate root rather than current
+    /// module (like paths in an import).
     pub global: bool,
+    /// The segments in the path: the things separated by `::`.
     pub segments: Vec<PathSegment>,
 }
 
 impl<T> From<T> for Path
     where T: Into<PathSegment>
 {
     fn from(segment: T) -> Self {
         Path {
@@ -70,17 +81,23 @@ impl<T> From<T> for Path
     }
 }
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
 ///
 /// E.g. `std`, `String` or `Box<T>`
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct PathSegment {
+    /// The identifier portion of this path segment.
     pub ident: Ident,
+    /// Type/lifetime parameters attached to this path. They come in
+    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
+    /// this is more than just simple syntactic sugar; the use of
+    /// parens affects the region binding rules, so we preserve the
+    /// distinction.
     pub parameters: PathParameters,
 }
 
 impl<T> From<T> for PathSegment
     where T: Into<Ident>
 {
     fn from(ident: T) -> Self {
         PathSegment {
@@ -223,21 +240,27 @@ pub mod parsing {
     #[cfg(feature = "full")]
     use ConstExpr;
     use constant::parsing::const_expr;
     #[cfg(feature = "full")]
     use expr::parsing::expr;
     use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
     use ident::parsing::ident;
     use lit::parsing::quoted_string;
+    #[cfg(feature = "type-macros")]
+    use mac::parsing::mac;
+    #[cfg(not(feature = "type-macros"))]
+    use nom::IResult;
     use std::str;
 
     named!(pub ty -> Ty, alt!(
         ty_paren // must be before ty_tup
         |
+        ty_mac // must be before ty_path
+        |
         ty_path // must be before ty_poly_trait_ref
         |
         ty_vec
         |
         ty_array
         |
         ty_ptr
         |
@@ -249,16 +272,24 @@ pub mod parsing {
         |
         ty_tup
         |
         ty_poly_trait_ref
         |
         ty_impl_trait
     ));
 
+    #[cfg(feature = "type-macros")]
+    named!(ty_mac -> Ty, map!(mac, Ty::Mac));
+
+    #[cfg(not(feature = "type-macros"))]
+    fn ty_mac(_: &str) -> IResult<&str, Ty> {
+        IResult::Error
+    }
+
     named!(ty_vec -> Ty, do_parse!(
         punct!("[") >>
         elem: ty >>
         punct!("]") >>
         (Ty::Slice(Box::new(elem)))
     ));
 
     #[cfg(not(feature = "full"))]
@@ -643,16 +674,17 @@ mod printing {
                 Ty::Paren(ref inner) => {
                     tokens.append("(");
                     inner.to_tokens(tokens);
                     tokens.append(")");
                 }
                 Ty::Infer => {
                     tokens.append("_");
                 }
+                Ty::Mac(ref mac) => mac.to_tokens(tokens),
             }
         }
     }
 
     impl ToTokens for Mutability {
         fn to_tokens(&self, tokens: &mut Tokens) {
             if let Mutability::Mutable = *self {
                 tokens.append("mut");
@@ -818,9 +850,16 @@ mod printing {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append("extern");
             match *self {
                 Abi::Named(ref named) => named.to_tokens(tokens),
                 Abi::Rust => {}
             }
         }
     }
+
+    #[cfg(not(feature = "type-macros"))]
+    impl ToTokens for Mac {
+        fn to_tokens(&self, _tokens: &mut Tokens) {
+            unreachable!()
+        }
+    }
 }
--- a/third_party/rust/syn/src/visit.rs
+++ b/third_party/rust/syn/src/visit.rs
@@ -166,16 +166,17 @@ pub fn walk_ty<V: Visitor>(visitor: &mut
         Ty::Array(ref inner, ref len) => {
             visitor.visit_ty(inner);
             visitor.visit_const_expr(len);
         }
         Ty::PolyTraitRef(ref bounds) |
         Ty::ImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
+        Ty::Mac(_) => {}
     }
 }
 
 pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
     for segment in &path.segments {
         visitor.visit_path_segment(segment);
     }
 }
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"84fa18694c3dbe743dea94e2d82b8fcafe4bf2184fedac42ecef09959a4fa726",".travis.yml":"2b8ad9e064f35fd10d4d25f42642ee5b908c63c1007dca6f4ad1e968865a98e2","COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"a3a1eebfe55b7891d6417f12b8eb4b0f60d84c50b4b2059505ec7252fe5ca224","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"d63c6bb1e9b9d65cccde3fe373f056ea16a439239f37f49977b9a3bee23ee465","scripts/unicode.py":"c18a8aab222162dcd92424dfdf0b8514f35bcf4a3fe88c469572abc969f814a1","src/lib.rs":"a389b616bc392b4c1fdad8571635f1f3e0279c6500d9abd645d058e1b690e61f","src/tables.rs":"91c7395f29b36c5736773845b5ce170f6083e3abbb258f27c61e15409e409314","src/tests.rs":"63ec5d241492102ad42e76b4d94ddfedd4468997a5627abb2090b9b872aaab31"},"package":"36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-target
-Cargo.lock
-scripts/tmp
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/.travis.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-language: rust
-rust: 'nightly'
-sudo: false
-script:
-  - cargo build --verbose --features no_std
-  - cargo test --verbose --features no_std
-  - cargo clean
-  - cargo build --verbose --features default
-  - cargo test --verbose --features default
-  - cargo bench --verbose --features default
-  - rustdoc --test README.md -L target/debug -L target/debug/deps
-  - cargo doc
-after_success: |
-  [ $TRAVIS_BRANCH = master ] &&
-  [ $TRAVIS_PULL_REQUEST = false ] &&
-  echo '<meta http-equiv=refresh content=0;url=unicode_xid/index.html>' > target/doc/index.html &&
-  pip install ghp-import --user $USER &&
-  $HOME/.local/bin/ghp-import -n target/doc &&
-  git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
-env:
-  global:
-    secure: gTlge+/OQlVkV0R+RThWXeN0aknmS7iUTPBMYKJyRdLz7T2vubw3w80a2CVE87JlpV87A5cVGD+LgR+AhYrhKtvqHb1brMDd99gylBBi2DfV7YapDSwSCuFgVR+FjZfJRcXBtI8po5urUZ84V0WLzRX8SyWqWgoD3oCkSL3Wp3w=
-notifications:
-  email:
-    on_success: never
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/COPYRIGHT
+++ /dev/null
@@ -1,7 +0,0 @@
-Licensed under the Apache License, Version 2.0
-<LICENSE-APACHE or
-http://www.apache.org/licenses/LICENSE-2.0> or the MIT
-license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
-at your option. All files in the project carrying such
-notice may not be copied, modified, or distributed except
-according to those terms.
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/Cargo.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-[package]
-
-name = "unicode-xid"
-version = "0.0.3"
-authors = ["erick.tryzelaar <erick.tryzelaar@gmail.com>",
-           "kwantam <kwantam@gmail.com>",
-           ]
-
-homepage = "https://github.com/unicode-rs/unicode-xid"
-repository = "https://github.com/unicode-rs/unicode-xid"
-documentation = "https://unicode-rs.github.io/unicode-xid"
-license = "MIT/Apache-2.0"
-keywords = ["text", "unicode", "xid"]
-readme = "README.md"
-description = """
-Determine whether characters have the XID_Start
-or XID_Continue properties according to
-Unicode Standard Annex #31.
-"""
-
-exclude = [ "target/*", "Cargo.lock" ]
-
-[features]
-default = []
-no_std = []
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2015 The Rust Project Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# unicode-xid
-
-Determine if a `char` is a valid identifier for a parser and/or lexer according to
-[Unicode Standard Annex #31](http://www.unicode.org/reports/tr31/) rules.
-
-[![Build Status](https://travis-ci.org/unicode-rs/unicode-xid.svg)](https://travis-ci.org/unicode-rs/unicode-xid)
-
-[Documentation](https://unicode-rs.github.io/unicode-xid/unicode_xid/index.html)
-
-```rust
-extern crate unicode_xid;
-
-use unicode_xid::UnicodeXID;
-
-fn main() {
-    let ch = 'a';
-    println!("Is {} a valid start of an identifier? {}", ch, UnicodeXID::is_xid_start(ch));
-}
-```
-
-# features
-
-unicode-xid supports a `no_std` feature. This eliminates dependence
-on std, and instead uses equivalent functions from core.
-
-# crates.io
-
-You can use this package in your project by adding the following
-to your `Cargo.toml`:
-
-```toml
-[dependencies]
-unicode-derived_property = "0.0.3"
-```
deleted file mode 100755
--- a/third_party/rust/unicode-xid-0.0.3/scripts/unicode.py
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2011-2015 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-# This script uses the following Unicode tables:
-# - DerivedCoreProperties.txt
-# - ReadMe.txt
-#
-# Since this should not require frequent updates, we just store this
-# out-of-line and check the unicode.rs file into git.
-
-import fileinput, re, os, sys
-
-preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// NOTE: The following code was generated by "scripts/unicode.py", do not edit directly
-
-#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
-'''
-
-def fetch(f):
-    if not os.path.exists(os.path.basename(f)):
-        os.system("curl -O http://www.unicode.org/Public/UNIDATA/%s"
-                  % f)
-
-    if not os.path.exists(os.path.basename(f)):
-        sys.stderr.write("cannot load %s" % f)
-        exit(1)
-
-def group_cat(cat):
-    cat_out = []
-    letters = sorted(set(cat))
-    cur_start = letters.pop(0)
-    cur_end = cur_start
-    for letter in letters:
-        assert letter > cur_end, \
-            "cur_end: %s, letter: %s" % (hex(cur_end), hex(letter))
-        if letter == cur_end + 1:
-            cur_end = letter
-        else:
-            cat_out.append((cur_start, cur_end))
-            cur_start = cur_end = letter
-    cat_out.append((cur_start, cur_end))
-    return cat_out
-
-def ungroup_cat(cat):
-    cat_out = []
-    for (lo, hi) in cat:
-        while lo <= hi:
-            cat_out.append(lo)
-            lo += 1
-    return cat_out
-
-def format_table_content(f, content, indent):
-    line = " "*indent
-    first = True
-    for chunk in content.split(","):
-        if len(line) + len(chunk) < 98:
-            if first:
-                line += chunk
-            else:
-                line += ", " + chunk
-            first = False
-        else:
-            f.write(line + ",\n")
-            line = " "*indent + chunk
-    f.write(line)
-
-def load_properties(f, interestingprops):
-    fetch(f)
-    props = {}
-    re1 = re.compile("^ *([0-9A-F]+) *; *(\w+)")
-    re2 = re.compile("^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)")
-
-    for line in fileinput.input(os.path.basename(f)):
-        prop = None
-        d_lo = 0
-        d_hi = 0
-        m = re1.match(line)
-        if m:
-            d_lo = m.group(1)
-            d_hi = m.group(1)
-            prop = m.group(2)
-        else:
-            m = re2.match(line)
-            if m:
-                d_lo = m.group(1)
-                d_hi = m.group(2)
-                prop = m.group(3)
-            else:
-                continue
-        if interestingprops and prop not in interestingprops:
-            continue
-        d_lo = int(d_lo, 16)
-        d_hi = int(d_hi, 16)
-        if prop not in props:
-            props[prop] = []
-        props[prop].append((d_lo, d_hi))
-
-    # optimize if possible
-    for prop in props:
-        props[prop] = group_cat(ungroup_cat(props[prop]))
-
-    return props
-
-def escape_char(c):
-    return "'\\u{%x}'" % c
-
-def emit_bsearch_range_table(f):
-    f.write("""
-fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
-    #[cfg(feature = "no_std")]
-    use core::cmp::Ordering::{Equal, Less, Greater};
-
-    #[cfg(feature = "no_std")]
-    use core::slice::SliceExt;
-
-    #[cfg(not(feature = "no_std"))]
-    use std::cmp::Ordering::{Equal, Less, Greater};
-
-    r.binary_search_by(|&(lo,hi)| {
-        if lo <= c && c <= hi { Equal }
-        else if hi < c { Less }
-        else { Greater }
-    }).is_ok()
-}\n
-""")
-
-def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True,
-        pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1])), is_const=True):
-    pub_string = "const"
-    if not is_const:
-        pub_string = "let"
-    if is_pub:
-        pub_string = "pub " + pub_string
-    f.write("    %s %s: %s = &[\n" % (pub_string, name, t_type))
-    data = ""
-    first = True
-    for dat in t_data:
-        if not first:
-            data += ","
-        first = False
-        data += pfun(dat)
-    format_table_content(f, data, 8)
-    f.write("\n    ];\n\n")
-
-def emit_property_module(f, mod, tbl, emit):
-    f.write("pub mod %s {\n" % mod)
-    for cat in sorted(emit):
-        emit_table(f, "%s_table" % cat, tbl[cat])
-        f.write("    pub fn %s(c: char) -> bool {\n" % cat)
-        f.write("        super::bsearch_range_table(c, %s_table)\n" % cat)
-        f.write("    }\n\n")
-    f.write("}\n\n")
-
-if __name__ == "__main__":
-    r = "tables.rs"
-    if os.path.exists(r):
-        os.remove(r)
-    with open(r, "w") as rf:
-        # write the file's preamble
-        rf.write(preamble)
-
-        # download and parse all the data
-        fetch("ReadMe.txt")
-        with open("ReadMe.txt") as readme:
-            pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
-            unicode_version = re.search(pattern, readme.read()).groups()
-        rf.write("""
-/// The version of [Unicode](http://www.unicode.org/)
-/// that this version of unicode-derived-property is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
-""" % unicode_version)
-        emit_bsearch_range_table(rf)
-
-        want_derived = ["XID_Start", "XID_Continue"]
-        derived = load_properties("DerivedCoreProperties.txt", want_derived)
-        emit_property_module(rf, "derived_property", derived, want_derived)
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/src/lib.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Determine if a `char` is a valid identifier for a parser and/or lexer according to
-//! [Unicode Standard Annex #31](http://www.unicode.org/reports/tr31/) rules.
-//!
-//! ```rust
-//! extern crate unicode_xid;
-//!
-//! use unicode_xid::UnicodeXID;
-//!
-//! fn main() {
-//!     let ch = 'a';
-//!     println!("Is {} a valid start of an identifier? {}", ch, UnicodeXID::is_xid_start(ch));
-//! }
-//! ```
-//!
-//! # features
-//!
-//! unicode-width supports a `no_std` feature. This eliminates dependence
-//! on std, and instead uses equivalent functions from core.
-//!
-//! # crates.io
-//!
-//! You can use this package in your project by adding the following
-//! to your `Cargo.toml`:
-//!
-//! ```toml
-//! [dependencies]
-//! unicode-derived_property = "0.0.1"
-//! ```
-
-#![deny(missing_docs, unsafe_code)]
-#![doc(html_logo_url = "https://unicode-rs.github.io/unicode-rs_sm.png",
-       html_favicon_url = "https://unicode-rs.github.io/unicode-rs_sm.png")]
-
-#![cfg_attr(feature = "no_std", no_std)]
-#![cfg_attr(feature = "no_std", feature(no_std, core_slice_ext))]
-
-#![cfg_attr(test, feature(test, unicode))]
-
-#[cfg(all(test, feature = "no_std"))]
-#[macro_use]
-extern crate std;
-
-#[cfg(test)]
-extern crate test;
-
-use tables::derived_property;
-pub use tables::UNICODE_VERSION;
-
-mod tables;
-
-#[cfg(test)]
-mod tests;
-
-/// Methods for determining if a character is a valid identifier character.
-pub trait UnicodeXID {
-    /// Returns whether the specified character satisfies the 'XID_Start'
-    /// Unicode property.
-    ///
-    /// 'XID_Start' is a Unicode Derived Property specified in
-    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to ID_Start but modified for closure under NFKx.
-    fn is_xid_start(self) -> bool;
-
-    /// Returns whether the specified `char` satisfies the 'XID_Continue'
-    /// Unicode property.
-    ///
-    /// 'XID_Continue' is a Unicode Derived Property specified in
-    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
-    fn is_xid_continue(self) -> bool;
-}
-
-impl UnicodeXID for char {
-    #[inline]
-    fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
-
-    #[inline]
-    fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
-}
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/src/tables.rs
+++ /dev/null
@@ -1,419 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// NOTE: The following code was generated by "scripts/unicode.py", do not edit directly
-
-#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
-
-/// The version of [Unicode](http://www.unicode.org/)
-/// that this version of unicode-derived-property is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (8, 0, 0);
-
-fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
-    #[cfg(feature = "no_std")]
-    use core::cmp::Ordering::{Equal, Less, Greater};
-
-    #[cfg(feature = "no_std")]
-    use core::slice::SliceExt;
-
-    #[cfg(not(feature = "no_std"))]
-    use std::cmp::Ordering::{Equal, Less, Greater};
-
-    r.binary_search_by(|&(lo,hi)| {
-        if lo <= c && c <= hi { Equal }
-        else if hi < c { Less }
-        else { Greater }
-    }).is_ok()
-}
-
-pub mod derived_property {
-    pub const XID_Continue_table: &'static [(char, char)] = &[
-        ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'), ('\u{61}', '\u{7a}'),
-        ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{b7}', '\u{b7}'), ('\u{ba}', '\u{ba}'),
-        ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
-        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{300}',
-        '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'), ('\u{37f}', '\u{37f}'),
-        ('\u{386}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}',
-        '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{483}', '\u{487}'), ('\u{48a}', '\u{52f}'),
-        ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{591}',
-        '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
-        ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{610}',
-        '\u{61a}'), ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'),
-        ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'), ('\u{710}',
-        '\u{74a}'), ('\u{74d}', '\u{7b1}'), ('\u{7c0}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
-        ('\u{800}', '\u{82d}'), ('\u{840}', '\u{85b}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}',
-        '\u{963}'), ('\u{966}', '\u{96f}'), ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'),
-        ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}',
-        '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
-        ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'), ('\u{9df}',
-        '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'),
-        ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}',
-        '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
-        ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a51}',
-        '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a66}', '\u{a75}'),
-        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}',
-        '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
-        ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}',
-        '\u{ad0}'), ('\u{ae0}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'),
-        ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}',
-        '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'),
-        ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'), ('\u{b56}',
-        '\u{b57}'), ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b6f}'),
-        ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}',
-        '\u{b90}'), ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
-        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}',
-        '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
-        ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{bef}'), ('\u{c00}',
-        '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'),
-        ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}',
-        '\u{c4d}'), ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'),
-        ('\u{c66}', '\u{c6f}'), ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}',
-        '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'),
-        ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'), ('\u{cd5}',
-        '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{ce6}', '\u{cef}'),
-        ('\u{cf1}', '\u{cf2}'), ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}',
-        '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
-        ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d66}',
-        '\u{d6f}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'),
-        ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}',
-        '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
-        ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df3}'), ('\u{e01}',
-        '\u{e3a}'), ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'),
-        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}',
-        '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'),
-        ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}',
-        '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}'), ('\u{f00}',
-        '\u{f00}'), ('\u{f18}', '\u{f19}'), ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'),
-        ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'), ('\u{f49}',
-        '\u{f6c}'), ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'), ('\u{f99}', '\u{fbc}'),
-        ('\u{fc6}', '\u{fc6}'), ('\u{1000}', '\u{1049}'), ('\u{1050}', '\u{109d}'), ('\u{10a0}',
-        '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'),
-        ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}',
-        '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'),
-        ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
-        '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'),
-        ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{135f}'), ('\u{1369}',
-        '\u{1371}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'),
-        ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1714}'),
-        ('\u{1720}', '\u{1734}'), ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}',
-        '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'), ('\u{17d7}', '\u{17d7}'),
-        ('\u{17dc}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'), ('\u{180b}', '\u{180d}'), ('\u{1810}',
-        '\u{1819}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'),
-        ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}', '\u{193b}'), ('\u{1946}',
-        '\u{196d}'), ('\u{1970}', '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'),
-        ('\u{19d0}', '\u{19da}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'), ('\u{1a60}',
-        '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'), ('\u{1a90}', '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'),
-        ('\u{1ab0}', '\u{1abd}'), ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'), ('\u{1b6b}',
-        '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}', '\u{1c37}'), ('\u{1c40}', '\u{1c49}'),
-        ('\u{1c4d}', '\u{1c7d}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}',
-        '\u{1cf9}'), ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'),
-        ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
-        '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'),
-        ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}',
-        '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
-        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'), ('\u{203f}',
-        '\u{2040}'), ('\u{2054}', '\u{2054}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
-        ('\u{2090}', '\u{209c}'), ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'), ('\u{20e5}',
-        '\u{20f0}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'),
-        ('\u{2115}', '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
-        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
-        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}',
-        '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'),
-        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}',
-        '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
-        ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
-        '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'),
-        ('\u{2de0}', '\u{2dff}'), ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}',
-        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{3099}', '\u{309a}'),
-        ('\u{309d}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}',
-        '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}', '\u{31ff}'),
-        ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}',
-        '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a66f}'),
-        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}',
-        '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'),
-        ('\u{a840}', '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'), ('\u{a8e0}',
-        '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a900}', '\u{a92d}'),
-        ('\u{a930}', '\u{a953}'), ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}',
-        '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'),
-        ('\u{aa50}', '\u{aa59}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}',
-        '\u{aadd}'), ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}', '\u{ab06}'),
-        ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}',
-        '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'),
-        ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}',
-        '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'),
-        ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}',
-        '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'),
-        ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}',
-        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdf9}'),
-        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}',
-        '\u{fe4f}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}', '\u{fe73}'), ('\u{fe77}', '\u{fe77}'),
-        ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'), ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}',
-        '\u{fefc}'), ('\u{ff10}', '\u{ff19}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'),
-        ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
-        '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'),
-        ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
-        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'),
-        ('\u{10140}', '\u{10174}'), ('\u{101fd}', '\u{101fd}'), ('\u{10280}', '\u{1029c}'),
-        ('\u{102a0}', '\u{102d0}'), ('\u{102e0}', '\u{102e0}'), ('\u{10300}', '\u{1031f}'),
-        ('\u{10330}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'),
-        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}', '\u{103d5}'),
-        ('\u{10400}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}'), ('\u{10500}', '\u{10527}'),
-        ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'),
-        ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'),
-        ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'),
-        ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'),
-        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'),
-        ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'),
-        ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}', '\u{10a13}'),
-        ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a38}', '\u{10a3a}'),
-        ('\u{10a3f}', '\u{10a3f}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'),
-        ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}', '\u{10b35}'),
-        ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'),
-        ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'),
-        ('\u{11000}', '\u{11046}'), ('\u{11066}', '\u{1106f}'), ('\u{1107f}', '\u{110ba}'),
-        ('\u{110d0}', '\u{110e8}'), ('\u{110f0}', '\u{110f9}'), ('\u{11100}', '\u{11134}'),
-        ('\u{11136}', '\u{1113f}'), ('\u{11150}', '\u{11173}'), ('\u{11176}', '\u{11176}'),
-        ('\u{11180}', '\u{111c4}'), ('\u{111ca}', '\u{111cc}'), ('\u{111d0}', '\u{111da}'),
-        ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{11237}'),
-        ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
-        ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112ea}'),
-        ('\u{112f0}', '\u{112f9}'), ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'),
-        ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
-        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}', '\u{11344}'),
-        ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11350}', '\u{11350}'),
-        ('\u{11357}', '\u{11357}'), ('\u{1135d}', '\u{11363}'), ('\u{11366}', '\u{1136c}'),
-        ('\u{11370}', '\u{11374}'), ('\u{11480}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'),
-        ('\u{114d0}', '\u{114d9}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115c0}'),
-        ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{11640}'), ('\u{11644}', '\u{11644}'),
-        ('\u{11650}', '\u{11659}'), ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}'),
-        ('\u{11700}', '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}', '\u{11739}'),
-        ('\u{118a0}', '\u{118e9}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'),
-        ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'),
-        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'),
-        ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16ad0}', '\u{16aed}'),
-        ('\u{16af0}', '\u{16af4}'), ('\u{16b00}', '\u{16b36}'), ('\u{16b40}', '\u{16b43}'),
-        ('\u{16b50}', '\u{16b59}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'),
-        ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}', '\u{16f9f}'),
-        ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'),
-        ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9d}', '\u{1bc9e}'),
-        ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'),
-        ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'),
-        ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
-        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'),
-        ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'),
-        ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'),
-        ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'),
-        ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
-        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'),
-        ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'),
-        ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'),
-        ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'),
-        ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'),
-        ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'),
-        ('\u{1daa1}', '\u{1daaf}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8d0}', '\u{1e8d6}'),
-        ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'),
-        ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'),
-        ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
-        ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
-        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'),
-        ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'),
-        ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'),
-        ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
-        ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
-        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'),
-        ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'),
-        ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'),
-        ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'), ('\u{e0100}', '\u{e01ef}')
-    ];
-
-    pub fn XID_Continue(c: char) -> bool {
-        super::bsearch_range_table(c, XID_Continue_table)
-    }
-
-    pub const XID_Start_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
-        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'),
-        ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}',
-        '\u{2ee}'), ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}',
-        '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'),
-        ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}',
-        '\u{587}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'),
-        ('\u{66e}', '\u{66f}'), ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}',
-        '\u{6e6}'), ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
-        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'), ('\u{7b1}',
-        '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
-        ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'), ('\u{824}', '\u{824}'), ('\u{828}',
-        '\u{828}'), ('\u{840}', '\u{858}'), ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'),
-        ('\u{93d}', '\u{93d}'), ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}',
-        '\u{980}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
-        ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bd}',
-        '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e1}'),
-        ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}',
-        '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'),
-        ('\u{a38}', '\u{a39}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}',
-        '\u{a74}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
-        ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abd}',
-        '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'), ('\u{af9}', '\u{af9}'),
-        ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}',
-        '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'),
-        ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}',
-        '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
-        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}',
-        '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'), ('\u{bd0}', '\u{bd0}'),
-        ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}',
-        '\u{c39}'), ('\u{c3d}', '\u{c3d}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'),
-        ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}',
-        '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'),
-        ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}',
-        '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'), ('\u{d4e}', '\u{d4e}'),
-        ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}',
-        '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'),
-        ('\u{e01}', '\u{e30}'), ('\u{e32}', '\u{e32}'), ('\u{e40}', '\u{e46}'), ('\u{e81}',
-        '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
-        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}',
-        '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'),
-        ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb2}'), ('\u{ebd}', '\u{ebd}'), ('\u{ec0}',
-        '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
-        ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
-        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'), ('\u{105a}', '\u{105d}'),
-        ('\u{1061}', '\u{1061}'), ('\u{1065}', '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}',
-        '\u{1081}'), ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'),
-        ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}',
-        '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
-        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}',
-        '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'),
-        ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}',
-        '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'),
-        ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1711}'),
-        ('\u{1720}', '\u{1731}'), ('\u{1740}', '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}',
-        '\u{1770}'), ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'),
-        ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'), ('\u{18aa}', '\u{18aa}'), ('\u{18b0}',
-        '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}', '\u{1a16}'), ('\u{1a20}',
-        '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'),
-        ('\u{1b83}', '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'), ('\u{1c00}',
-        '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'),
-        ('\u{1cee}', '\u{1cf1}'), ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}',
-        '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
-        ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
-        '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}',
-        '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
-        ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}',
-        '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'),
-        ('\u{2115}', '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
-        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
-        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}',
-        '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'),
-        ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
-        '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'),
-        ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
-        '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
-        ('\u{2dd8}', '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3031}',
-        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'),
-        ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'), ('\u{3131}',
-        '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'),
-        ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
-        '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'),
-        ('\u{a67f}', '\u{a69d}'), ('\u{a6a0}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}',
-        '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'),
-        ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'),
-        ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}',
-        '\u{a97c}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'),
-        ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'), ('\u{aa40}',
-        '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
-        ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}',
-        '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'),
-        ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}',
-        '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'),
-        ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abe2}'), ('\u{ac00}',
-        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'),
-        ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}',
-        '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'),
-        ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}',
-        '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'),
-        ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdf9}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}',
-        '\u{fe73}'), ('\u{fe77}', '\u{fe77}'), ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'),
-        ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}',
-        '\u{ff5a}'), ('\u{ff66}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'),
-        ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}',
-        '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}',
-        '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
-        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}',
-        '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{1034a}'), ('\u{10350}',
-        '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}',
-        '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}',
-        '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
-        '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}',
-        '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}',
-        '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}',
-        '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
-        '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
-        '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}',
-        '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}',
-        '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}',
-        '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}',
-        '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}',
-        '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'), ('\u{110d0}',
-        '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', '\u{11172}'), ('\u{11176}',
-        '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}',
-        '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
-        '\u{1122b}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}',
-        '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}',
-        '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}',
-        '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}',
-        '\u{11339}'), ('\u{1133d}', '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}',
-        '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}',
-        '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'), ('\u{11600}',
-        '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'), ('\u{11700}',
-        '\u{11719}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}',
-        '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}',
-        '\u{12543}'), ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
-        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}',
-        '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
-        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), ('\u{16f93}',
-        '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}',
-        '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}',
-        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}',
-        '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}',
-        '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}',
-        '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}',
-        '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
-        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}',
-        '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}',
-        '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}',
-        '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}',
-        '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}',
-        '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}',
-        '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}',
-        '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}',
-        '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
-        '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
-        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}',
-        '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}',
-        '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}',
-        '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
-        '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
-        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}',
-        '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}',
-        '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}')
-    ];
-
-    pub fn XID_Start(c: char) -> bool {
-        super::bsearch_range_table(c, XID_Start_table)
-    }
-
-}
-
deleted file mode 100644
--- a/third_party/rust/unicode-xid-0.0.3/src/tests.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::iter;
-use test::Bencher;
-
-use super::UnicodeXID;
-
-#[cfg(feature = "no_std")]
-use std::prelude::v1::*;
-
-#[bench]
-fn cargo_is_xid_start(b: &mut Bencher) {
-    let string = iter::repeat('a').take(4096).collect::<String>();
-
-    b.bytes = string.len() as u64;
-    b.iter(|| {
-        string.chars().all(UnicodeXID::is_xid_start)
-    });
-}
-
-#[bench]
-fn stdlib_is_xid_start(b: &mut Bencher) {
-    let string = iter::repeat('a').take(4096).collect::<String>();
-
-    b.bytes = string.len() as u64;
-    b.iter(|| {
-        string.chars().all(char::is_xid_start)
-    });
-}
-
-#[bench]
-fn cargo_xid_continue(b: &mut Bencher) {
-    let string = iter::repeat('a').take(4096).collect::<String>();
-
-    b.bytes = string.len() as u64;
-    b.iter(|| {
-        string.chars().all(UnicodeXID::is_xid_continue)
-    });
-}
-
-#[bench]
-fn stdlib_xid_continue(b: &mut Bencher) {
-    let string = iter::repeat('a').take(4096).collect::<String>();
-
-    b.bytes = string.len() as u64;
-    b.iter(|| {
-        string.chars().all(char::is_xid_continue)
-    });
-}
-
-#[test]
-fn test_is_xid_start() {
-    let chars = [
-        'A', 'Z', 'a', 'z',
-        '\u{1000d}', '\u{10026}',
-    ];
-
-    for ch in &chars {
-        assert!(UnicodeXID::is_xid_start(*ch), "{}", ch);
-    }
-}
-
-#[test]
-fn test_is_not_xid_start() {
-    let chars = [
-        '\x00', '\x01',
-        '0', '9',
-        ' ', '[', '<', '{', '(',
-        '\u{02c2}', '\u{ffff}',
-    ];
-
-    for ch in &chars {
-        assert!(!UnicodeXID::is_xid_start(*ch), "{}", ch);
-    }
-}
-
-#[test]
-fn test_is_xid_continue() {
-    let chars = [
-        '0', '9', 'A', 'Z', 'a', 'z', '_',
-        '\u{1000d}', '\u{10026}',
-    ];
-
-    for ch in &chars {
-        assert!(UnicodeXID::is_xid_continue(*ch), "{}", ch);
-    }
-}
-
-#[test]
-fn test_is_not_xid_continue() {
-    let chars = [
-        '\x00', '\x01',
-        ' ', '[', '<', '{', '(',
-        '\u{02c2}', '\u{ffff}',
-    ];
-
-    for &ch in &chars {
-        assert!(!UnicodeXID::is_xid_continue(ch), "{}", ch);
-    }
-}
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -10,28 +10,28 @@ dependencies = [
 [[package]]
 name = "app_units"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bincode"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bit-set"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -62,17 +62,17 @@ name = "byteorder"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cgl"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-foundation"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -90,40 +90,40 @@ dependencies = [
 
 [[package]]
 name = "core-graphics"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "dwrote"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "error-chain"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -131,17 +131,17 @@ source = "registry+https://github.com/ru
 name = "euclid"
 version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fnv"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -183,21 +183,21 @@ source = "registry+https://github.com/ru
 dependencies = [
  "khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gleam"
-version = "0.2.30"
+version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "heapsize"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -248,17 +248,17 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "metadeps"
 version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mp4parse"
 version = "0.6.0"
 dependencies = [
  "bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -290,51 +290,51 @@ dependencies = [
 
 [[package]]
 name = "num-traits"
 version = "0.1.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "offscreen_gl_context"
-version = "0.5.1"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "osmesa-sys"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "pkg-config"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
-version = "0.3.11"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -348,55 +348,55 @@ dependencies = [
 
 [[package]]
 name = "rustc-serialize"
 version = "0.3.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "0.8.22"
+version = "0.8.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_codegen"
-version = "0.8.22"
+version = "0.8.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_codegen_internals"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "shared_library"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syntex"
 version = "0.54.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -479,21 +479,16 @@ dependencies = [
 
 [[package]]
 name = "unicode-normalization"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "unicode-xid"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "url"
 version = "1.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -516,59 +511,59 @@ version = "0.11.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.11.0",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender 0.11.1",
  "webrender_traits 0.11.0",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender_traits"
 version = "0.11.0"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -602,55 +597,54 @@ dependencies = [
 "checksum bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8319aa6588c40cce19a135009ec70dc730a34ed9d27bab2409298b948546da7a"
 "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
 "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
 "checksum cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"
 "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
 "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
 "checksum core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd94d0f0b2bbcbfeeb670fc48654afde7a13c2c551ca9d2b9a6cfafdafe1a64"
 "checksum core-text 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "642fa40165b6c53bbd3f636951ffc3e1a3fd3c47e7d00598523c3e8c9321ed0c"
-"checksum dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "570707c940fc7b7fc627011fe2c8abedaea562b03bde715e3ee2dd3d6857a03c"
+"checksum dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c3d72c5042f43ee02587b5f3256efc6252c2194fbbb0dfa0bd0b6da2491501"
 "checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
 "checksum euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c274f13773ec277a48408d0c7a8dc935ad4bfe190f4cfccd0126d203afc3c83"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
-"checksum gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "6af023107aa969ccf8868a0304fead4b2f813c19aa9a6a243fddc041f3e51da5"
+"checksum gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3023edde169b7767a71d2e5dd8e8903ac3b1436ff659225310928db87d6a8a"
 "checksum heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a376f7402b85be6e0ba504243ecbc0709c48019ecc6286d0540c2e359050c88"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
 "checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151"
 "checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
-"checksum offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2fe2fe54ba2b6ea8f43a17b16c13168c5bbf008e0fc91b34122a11f637e2728a"
+"checksum offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2092c6bb5550536a097c5b413a2c36e141bc63c85c0a40944a182c1912d69397"
 "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
-"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
-"checksum quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48f961356de2df29263e751df9e2e2493bd765e57fce250cc8b8dcef53ed33c0"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
-"checksum serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4aab5b62fb90ac9c99d5a55caa7c37e06a15d1b189ccc2b117782655fd11f"
-"checksum serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "200c97dd86298518356c694869a7a51af1de398bd6c6dcce89fa21a512fdea44"
+"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
+"checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc"
 "checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806"
 "checksum shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04126b6fcfd2710fb5b6d18f4207b6c535f2850a7e1a43bcd526d44f30a79a"
-"checksum syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "17134635792e6a2361f53efbee798701796d8b5842c1c21b7cdb875e2950c8fc"
+"checksum syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e5aaf7e4a0f90d7285445c881dcc28f1a510e4962b4ffcdde17f5775b2960df6"
 "checksum syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3f52553a966675982404dc34028291b347e0c9a9c0b0b34f2da6be8a0443f8"
 "checksum syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee2f6e49c075f71332bb775219d5982bee6732d26227fa1ae1b53cdb12f5cc5"
 "checksum syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df3921c7945dfb9ffc53aa35adb2cf4313b5ab5f079c3619b3d4eb82a0efc2b"
 "checksum syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc960085bae44591e22d01f6c0e82a8aec832f8659aca556cdf8ecbdac2bb47b"
 "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
 "checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1"
 "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
 "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
-"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f024e241a55f5c88401595adc1d4af0c9649e91da82d0e190fe55950231ae575"
 "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "124eb405bf0262a54e1a982d4ffe4cd1c24261bdb306e49996e2ce7d492284a8"
 "checksum xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b15eed12692bd59d15e98ee7f8dc8408465b992d8ddb4d1672c24865132ec7"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -8,28 +8,28 @@ dependencies = [
 [[package]]
 name = "app_units"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bincode"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bit-set"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -60,17 +60,17 @@ name = "byteorder"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cgl"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-foundation"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -88,40 +88,40 @@ dependencies = [
 
 [[package]]
 name = "core-graphics"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "dwrote"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "error-chain"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -129,17 +129,17 @@ source = "registry+https://github.com/ru
 name = "euclid"
 version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fnv"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -181,21 +181,21 @@ source = "registry+https://github.com/ru
 dependencies = [
  "khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gleam"
-version = "0.2.30"
+version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "heapsize"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -246,17 +246,17 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "metadeps"
 version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mp4parse"
 version = "0.6.0"
 dependencies = [
  "bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -277,51 +277,51 @@ version = "0.1.0"
 
 [[package]]
 name = "num-traits"
 version = "0.1.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "offscreen_gl_context"
-version = "0.5.1"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "osmesa-sys"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "pkg-config"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
-version = "0.3.11"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -335,55 +335,55 @@ dependencies = [
 
 [[package]]
 name = "rustc-serialize"
 version = "0.3.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "0.8.22"
+version = "0.8.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_codegen"
-version = "0.8.22"
+version = "0.8.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_codegen_internals"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "shared_library"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syntex"
 version = "0.54.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -466,21 +466,16 @@ dependencies = [
 
 [[package]]
 name = "unicode-normalization"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "unicode-xid"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "url"
 version = "1.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -503,59 +498,59 @@ version = "0.11.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.11.0",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender 0.11.1",
  "webrender_traits 0.11.0",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender_traits"
 version = "0.11.0"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -589,55 +584,54 @@ dependencies = [
 "checksum bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8319aa6588c40cce19a135009ec70dc730a34ed9d27bab2409298b948546da7a"
 "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
 "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
 "checksum cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"
 "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
 "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
 "checksum core-graphics 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd94d0f0b2bbcbfeeb670fc48654afde7a13c2c551ca9d2b9a6cfafdafe1a64"
 "checksum core-text 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "642fa40165b6c53bbd3f636951ffc3e1a3fd3c47e7d00598523c3e8c9321ed0c"
-"checksum dwrote 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "570707c940fc7b7fc627011fe2c8abedaea562b03bde715e3ee2dd3d6857a03c"
+"checksum dwrote 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c3d72c5042f43ee02587b5f3256efc6252c2194fbbb0dfa0bd0b6da2491501"
 "checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
 "checksum euclid 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c274f13773ec277a48408d0c7a8dc935ad4bfe190f4cfccd0126d203afc3c83"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
-"checksum gleam 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "6af023107aa969ccf8868a0304fead4b2f813c19aa9a6a243fddc041f3e51da5"
+"checksum gleam 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3023edde169b7767a71d2e5dd8e8903ac3b1436ff659225310928db87d6a8a"
 "checksum heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a376f7402b85be6e0ba504243ecbc0709c48019ecc6286d0540c2e359050c88"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
 "checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151"
 "checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
-"checksum offscreen_gl_context 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2fe2fe54ba2b6ea8f43a17b16c13168c5bbf008e0fc91b34122a11f637e2728a"
+"checksum offscreen_gl_context 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2092c6bb5550536a097c5b413a2c36e141bc63c85c0a40944a182c1912d69397"
 "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
-"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
-"checksum quote 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48f961356de2df29263e751df9e2e2493bd765e57fce250cc8b8dcef53ed33c0"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
-"checksum serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4aab5b62fb90ac9c99d5a55caa7c37e06a15d1b189ccc2b117782655fd11f"
-"checksum serde_codegen 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "200c97dd86298518356c694869a7a51af1de398bd6c6dcce89fa21a512fdea44"
+"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
+"checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc"
 "checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806"
 "checksum shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04126b6fcfd2710fb5b6d18f4207b6c535f2850a7e1a43bcd526d44f30a79a"
-"checksum syn 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "17134635792e6a2361f53efbee798701796d8b5842c1c21b7cdb875e2950c8fc"
+"checksum syn 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e5aaf7e4a0f90d7285445c881dcc28f1a510e4962b4ffcdde17f5775b2960df6"
 "checksum syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3f52553a966675982404dc34028291b347e0c9a9c0b0b34f2da6be8a0443f8"
 "checksum syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee2f6e49c075f71332bb775219d5982bee6732d26227fa1ae1b53cdb12f5cc5"
 "checksum syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df3921c7945dfb9ffc53aa35adb2cf4313b5ab5f079c3619b3d4eb82a0efc2b"
 "checksum syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc960085bae44591e22d01f6c0e82a8aec832f8659aca556cdf8ecbdac2bb47b"
 "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
 "checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1"
 "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
 "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
-"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f024e241a55f5c88401595adc1d4af0c9649e91da82d0e190fe55950231ae575"
 "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "124eb405bf0262a54e1a982d4ffe4cd1c24261bdb306e49996e2ce7d492284a8"
 "checksum xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b15eed12692bd59d15e98ee7f8dc8408465b992d8ddb4d1672c24865132ec7"