Merge inbound to mozilla-central. a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Fri, 21 Sep 2018 12:39:35 +0300
changeset 493352 8b93a94b92c3
parent 493339 8dc63538dff7 (current diff)
parent 493351 5d99742ecb5f (diff)
child 493365 1b266dbc1677
child 493408 c22852e1f4b2
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.0a1
first release with
nightly linux32
8b93a94b92c3 / 64.0a1 / 20180921100113 / files
nightly linux64
8b93a94b92c3 / 64.0a1 / 20180921100113 / files
nightly mac
8b93a94b92c3 / 64.0a1 / 20180921100113 / files
nightly win32
8b93a94b92c3 / 64.0a1 / 20180921100113 / files
nightly win64
8b93a94b92c3 / 64.0a1 / 20180921100113 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
ipc/chromium/src/base/process_util_bsd.cc
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -354,32 +354,32 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "core-graphics"
-version = "0.16.0"
+version = "0.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
-version = "11.0.0"
+version = "13.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cose"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2636,18 +2636,18 @@ name = "webrender"
 version = "0.57.2"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-text 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2665,33 +2665,33 @@ dependencies = [
 name = "webrender_api"
 version = "0.57.2"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2850,18 +2850,18 @@ dependencies = [
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
 "checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
 "checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
-"checksum core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92801c908ea6301ae619ed842a72e01098085fc321b9c2f3f833dad555bba055"
-"checksum core-text 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "157ff38a92496dc676ce36d9124554e9ac66f1c1039f952690ac64f71cfa5968"
+"checksum core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"
+"checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
 "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-epoch 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2af0e75710d6181e234c8ecc79f14a97907850a541b13b0be1dd10992f2e4620"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -583,22 +583,32 @@ async function fillInCardForm(frame, aCa
     // fill the form
     info("fillInCardForm: fill the form with card: " + JSON.stringify(card));
     for (let [key, val] of Object.entries(card)) {
       let field = content.document.getElementById(key);
       if (!field) {
         ok(false, `${key} field not found`);
       }
       ok(!field.disabled, `Field #${key} shouldn't be disabled`);
+      // Reset the value first so that we properly handle typing the value
+      // already selected which may select another option with the same prefix.
       field.value = "";
+      ok(!field.value, "Field value should be reset before typing");
+      field.blur();
       field.focus();
+      // Using waitForEvent here causes the test to hang, but
+      // waitForCondition and checking activeElement does the trick. The root cause
+      // of this should be investigated further.
+      await ContentTaskUtils.waitForCondition(() => field == content.document.activeElement,
+                                              `Waiting for field #${key} to get focus`);
       // cc-exp-* fields are numbers so convert to strings and pad left with 0
       let fillValue = val.toString().padStart(2, "0");
-      EventUtils.synthesizeKey(fillValue, {}, content.window);
-      ok(field.value, fillValue, `${key} value is correct after synthesizeKey`);
+      EventUtils.synthesizeKey(fillValue, {}, Cu.waiveXrays(content.window));
+      // cc-exp-* field values are not padded, so compare with unpadded string.
+      is(field.value, val.toString(), `${key} value is correct after sendString`);
     }
 
     info([...content.document.getElementById("cc-exp-year").options].map(op => op.label).join(","));
 
     let persistCheckbox = content.document.querySelector(options.checkboxSelector);
     // only touch the checked state if explicitly told to in the options
     if (options.hasOwnProperty("setPersistCheckedValue")) {
       info("fillInCardForm: Manually setting the persist checkbox checkedness to: " +
--- a/build/autoconf/sanitize.m4
+++ b/build/autoconf/sanitize.m4
@@ -129,16 +129,23 @@ if test -n "$MOZ_SIGNED_OVERFLOW_SANITIZ
     CXXFLAGS="$SANITIZER_BLACKLISTS $CXXFLAGS"
     AC_DEFINE(MOZ_UBSAN)
     MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
 fi
 AC_SUBST(MOZ_SIGNED_OVERFLOW_SANITIZE)
 AC_SUBST(MOZ_UNSIGNED_OVERFLOW_SANITIZE)
 AC_SUBST(MOZ_UBSAN)
 
+dnl =======================================================
+dnl = Required for stand-alone (sanitizer-less) libFuzzer.
+dnl =======================================================
+if test -n "$LIBFUZZER"; then
+   LDFLAGS="$LIBFUZZER_FLAGS -rdynamic $LDFLAGS"
+fi
+
 # The LLVM symbolizer is used by all sanitizers
 AC_SUBST(LLVM_SYMBOLIZER)
 
 dnl ========================================================
 dnl = Test for whether the compiler is compatible with the
 dnl = given sanitize options.
 dnl ========================================================
 AC_TRY_LINK(,,,AC_MSG_ERROR([compiler is incompatible with sanitize options]))
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -1850,22 +1850,33 @@ add_gcc_flag(
 add_gcc_flag(
     '-D_GLIBCXX_USE_CXX11_ABI=0', host_cxx_compiler,
     when=libstdcxx_version(
         'MOZ_LIBSTDCXX_HOST_VERSION', host_cxx_compiler, host))
 
 
 @depends(c_compiler.try_compile(flags=['-fsanitize=fuzzer-no-link'],
          check_msg='whether the C compiler supports -fsanitize=fuzzer-no-link'))
-def have_libfuzzer_flag_fuzzer_no_link(value):
+def libfuzzer_flags(value):
     if value:
-        return True
+        no_link_flag_supported = True
+        # recommended for (and only supported by) clang >= 6
+        use_flags = ['-fsanitize=fuzzer-no-link']
+    else:
+        no_link_flag_supported = False
+        use_flags = ['-fsanitize-coverage=trace-pc-guard,trace-cmp']
 
+    return namespace(
+        no_link_flag_supported=no_link_flag_supported,
+        use_flags=use_flags,
+    )
 
-set_config('HAVE_LIBFUZZER_FLAG_FUZZER_NO_LINK', have_libfuzzer_flag_fuzzer_no_link)
+set_config('HAVE_LIBFUZZER_FLAG_FUZZER_NO_LINK', libfuzzer_flags.no_link_flag_supported)
+set_config('LIBFUZZER_FLAGS', libfuzzer_flags.use_flags)
+add_old_configure_assignment('LIBFUZZER_FLAGS', libfuzzer_flags.use_flags)
 
 # Shared library building
 # ==============================================================
 
 # XXX: The use of makefile constructs in these variables is awful.
 @depends(target, c_compiler)
 def make_shared_library(target, compiler):
     if target.os == 'WINNT':
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -907,16 +907,17 @@ endif
 ifdef MOZ_USING_SCCACHE
 sccache_wrap := RUSTC_WRAPPER='$(CCACHE)'
 endif
 
 ifndef MOZ_ASAN
 ifndef MOZ_TSAN
 ifndef MOZ_UBSAN
 ifndef MOZ_CODE_COVERAGE
+ifndef FUZZING_INTERFACES
 # Pass the compilers and flags in use to cargo for use in build scripts.
 # * Don't do this for ASAN/TSAN builds because we don't pass our custom linker (see below)
 #   which will muck things up.
 # * Don't do this for code coverage builds because the way rustc invokes the linker doesn't
 #   work with GCC 6: https://bugzilla.mozilla.org/show_bug.cgi?id=1477305
 #
 # We don't pass HOST_{CC,CXX} down in any form because our host value might not match
 # what cargo chooses and there's no way to control cargo's selection, so we just have to
@@ -938,16 +939,17 @@ else
 cargo_c_compiler_envs := \
  CC_$(rust_cc_env_name)="$(CC)" \
  CXX_$(rust_cc_env_name)="$(CXX)" \
  CFLAGS_$(rust_cc_env_name)="$(COMPUTED_CFLAGS)" \
  CXXFLAGS_$(rust_cc_env_name)="$(COMPUTED_CXXFLAGS)" \
  AR_$(rust_cc_env_name)="$(AR)" \
  $(NULL)
 endif # WINNT
+endif # FUZZING_INTERFACES
 endif # MOZ_CODE_COVERAGE
 endif # MOZ_UBSAN
 endif # MOZ_TSAN
 endif # MOZ_ASAN
 
 # We use the + prefix to pass down the jobserver fds to cargo, but we
 # don't use the prefix when make -n is used, so that cargo doesn't run
 # in that case)
@@ -1003,24 +1005,26 @@ cargo_linker_env_var := CARGO_TARGET_$(R
 # have to pass in any special linker options on Windows.
 ifneq (WINNT,$(OS_ARCH))
 
 # Defining all of this for ASan/TSan builds results in crashes while running
 # some crates's build scripts (!), so disable it for now.
 ifndef MOZ_ASAN
 ifndef MOZ_TSAN
 ifndef MOZ_UBSAN
+ifndef FUZZING_INTERFACES
 # Cargo needs the same linker flags as the C/C++ compiler,
 # but not the final libraries. Filter those out because they
 # cause problems on macOS 10.7; see bug 1365993 for details.
 # Also, we don't want to pass PGO flags until cargo supports them.
 target_cargo_env_vars := \
 	MOZ_CARGO_WRAP_LDFLAGS="$(filter-out -fsanitize=cfi% -framework Cocoa -lobjc AudioToolbox ExceptionHandling -fprofile-%,$(LDFLAGS))" \
 	MOZ_CARGO_WRAP_LD="$(CC)" \
 	$(cargo_linker_env_var)=$(topsrcdir)/build/cargo-linker
+endif # FUZZING_INTERFACES
 endif # MOZ_UBSAN
 endif # MOZ_TSAN
 endif # MOZ_ASAN
 
 endif # ifneq WINNT
 
 ifdef RUST_LIBRARY_FILE
 
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -41,37 +41,41 @@ serde_json = { optional = true, version 
 smallvec = "0.6"
 thread_profiler = "0.1.1"
 time = "0.1"
 webrender_api = { version = "0.57.2", path = "../webrender_api" }
 ws = { optional = true, version = "0.7.3" }
 
 [dependencies.pathfinder_font_renderer]
 git = "https://github.com/pcwalton/pathfinder"
+branch = "webrender"
 optional = true
 # Uncomment to test FreeType on macOS:
 # features = ["freetype"]
 
 [dependencies.pathfinder_gfx_utils]
 git = "https://github.com/pcwalton/pathfinder"
+branch = "webrender"
 optional = true
 
 [dependencies.pathfinder_partitioner]
 git = "https://github.com/pcwalton/pathfinder"
+branch = "webrender"
 optional = true
 
 [dependencies.pathfinder_path_utils]
 git = "https://github.com/pcwalton/pathfinder"
+branch = "webrender"
 optional = true
 
 [dev-dependencies]
 mozangle = "0.1"
 
 [target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies]
 freetype = { version = "0.4", default-features = false }
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.4.1"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.6"
-core-graphics = "0.16"
-core-text = { version = "11", default-features = false }
+core-graphics = "0.17.1"
+core-text = { version = "13", default-features = false }
--- a/gfx/webrender/res/clip_shared.glsl
+++ b/gfx/webrender/res/clip_shared.glsl
@@ -54,29 +54,26 @@ RectWithSize intersect_rect(RectWithSize
 // which is the intersection of all clip instances of a given primitive
 ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
                                       Transform prim_transform,
                                       Transform clip_transform,
                                       ClipArea area) {
     vec2 device_pos = area.screen_origin +
                       aPosition.xy * area.common_data.task_rect.size;
 
-    // TODO(gw): We only check the clip transform matrix here. We should
-    //           probably also be checking the prim_transform matrix. I
-    //           have left it as is for now, since that matches the
-    //           previous behavior.
-    if (clip_transform.is_axis_aligned) {
+    if (clip_transform.is_axis_aligned && prim_transform.is_axis_aligned) {
+        mat4 snap_mat = clip_transform.m * prim_transform.inv_m;
         vec4 snap_positions = compute_snap_positions(
-            clip_transform.m,
+            snap_mat,
             local_clip_rect
         );
 
         vec2 snap_offsets = compute_snap_offset_impl(
             device_pos,
-            clip_transform.m,
+            snap_mat,
             local_clip_rect,
             RectWithSize(snap_positions.xy, snap_positions.zw - snap_positions.xy),
             snap_positions
         );
 
         device_pos -= snap_offsets;
     }
 
--- a/gfx/webrender/src/platform/macos/font.rs
+++ b/gfx/webrender/src/platform/macos/font.rs
@@ -5,45 +5,49 @@
 use api::{ColorU, FontKey, FontRenderMode, GlyphDimensions};
 use api::{FontInstanceFlags, FontVariation, NativeFontHandle};
 use app_units::Au;
 use core_foundation::array::{CFArray, CFArrayRef};
 use core_foundation::base::TCFType;
 use core_foundation::dictionary::CFDictionary;
 use core_foundation::number::{CFNumber, CFNumberRef};
 use core_foundation::string::{CFString, CFStringRef};
-use core_graphics::base::{kCGImageAlphaNoneSkipFirst, kCGBitmapByteOrder32Little};
-#[cfg(not(feature = "pathfinder"))]
-use core_graphics::base::kCGImageAlphaPremultipliedFirst;
+use core_graphics::base::{kCGImageAlphaNoneSkipFirst, kCGImageAlphaPremultipliedFirst};
+use core_graphics::base::{kCGBitmapByteOrder32Little};
 use core_graphics::color_space::CGColorSpace;
 use core_graphics::context::CGContext;
 #[cfg(not(feature = "pathfinder"))]
-use core_graphics::context::CGTextDrawingMode;
+use core_graphics::context::{CGBlendMode, CGTextDrawingMode};
 use core_graphics::data_provider::CGDataProvider;
 use core_graphics::font::{CGFont, CGGlyph};
 use core_graphics::geometry::{CGAffineTransform, CGPoint, CGSize};
 #[cfg(not(feature = "pathfinder"))]
-use core_graphics::geometry::CGRect;
+use core_graphics::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGRect};
 use core_text;
 use core_text::font::{CTFont, CTFontRef};
 use core_text::font_descriptor::{kCTFontDefaultOrientation, kCTFontColorGlyphsTrait};
+use euclid::Size2D;
 use gamma_lut::{ColorLut, GammaLut};
 use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey};
 #[cfg(feature = "pathfinder")]
 use glyph_rasterizer::NativeFontHandleWrapper;
 #[cfg(not(feature = "pathfinder"))]
 use glyph_rasterizer::{GlyphFormat, GlyphRasterResult, RasterizedGlyph};
 use internal_types::{FastHashMap, ResourceCacheError};
 use std::collections::hash_map::Entry;
 use std::sync::Arc;
 
+const INITIAL_CG_CONTEXT_SIDE_LENGTH: u32 = 32;
+
 pub struct FontContext {
     cg_fonts: FastHashMap<FontKey, CGFont>,
     ct_fonts: FastHashMap<(FontKey, Au, Vec<FontVariation>), CTFont>,
     #[allow(dead_code)]
+    graphics_context: GraphicsContext,
+    #[allow(dead_code)]
     gamma_lut: GammaLut,
 }
 
 // core text is safe to use on multiple threads and non-shareable resources are
 // all hidden inside their font context.
 unsafe impl Send for FontContext {}
 
 struct GlyphMetrics {
@@ -111,17 +115,19 @@ fn get_glyph_metrics(
             rasterized_height: 0,
             rasterized_ascent: 0,
             rasterized_descent: 0,
             advance: 0.0,
         };
     }
 
     let mut advance = CGSize { width: 0.0, height: 0.0 };
-    ct_font.get_advances_for_glyphs(kCTFontDefaultOrientation, &glyph, &mut advance, 1);
+    unsafe {
+        ct_font.get_advances_for_glyphs(kCTFontDefaultOrientation, &glyph, &mut advance, 1);
+    }
 
     if bounds.size.width > 0.0 {
         bounds.size.width += extra_width;
     }
     if advance.width > 0.0 {
         advance.width += extra_width;
     }
 
@@ -276,16 +282,17 @@ impl FontContext {
 
         // Force CG to use sRGB color space to gamma correct.
         let contrast = 0.0;
         let gamma = 0.0;
 
         Ok(FontContext {
             cg_fonts: FastHashMap::default(),
             ct_fonts: FastHashMap::default(),
+            graphics_context: GraphicsContext::new(),
             gamma_lut: GammaLut::new(contrast, gamma, gamma),
         })
     }
 
     pub fn has_font(&self, font_key: &FontKey) -> bool {
         self.cg_fonts.contains_key(font_key)
     }
 
@@ -339,22 +346,24 @@ impl FontContext {
     }
 
     pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
         let character = ch as u16;
         let mut glyph = 0;
 
         self.get_ct_font(font_key, Au::from_px(16), &[])
             .and_then(|ref ct_font| {
-                let result = ct_font.get_glyphs_for_characters(&character, &mut glyph, 1);
+                unsafe {
+                    let result = ct_font.get_glyphs_for_characters(&character, &mut glyph, 1);
 
-                if result {
-                    Some(glyph as u32)
-                } else {
-                    None
+                    if result {
+                        Some(glyph as u32)
+                    } else {
+                        None
+                    }
                 }
             })
     }
 
     pub fn get_glyph_dimensions(
         &mut self,
         font: &FontInstance,
         key: &GlyphKey,
@@ -489,21 +498,27 @@ impl FontContext {
         let (x_scale, y_scale) = font.transform.compute_scale().unwrap_or((1.0, 1.0));
         let scale = font.oversized_scale_factor(x_scale, y_scale);
         let size = font.size.scale_by((y_scale / scale) as f32);
         let ct_font = match self.get_ct_font(font.font_key, size, &font.variations) {
             Some(font) => font,
             None => return GlyphRasterResult::LoadFailed,
         };
 
-        let bitmap = is_bitmap_font(&ct_font);
-        let (mut shape, (x_offset, y_offset)) = if bitmap {
-            (FontTransform::identity(), (0.0, 0.0))
+        let glyph_type = if is_bitmap_font(&ct_font) {
+            GlyphType::Bitmap
         } else {
-            (font.transform.invert_scale(y_scale, y_scale), font.get_subpx_offset(key))
+            GlyphType::Vector
+        };
+
+        let (mut shape, (x_offset, y_offset)) = match glyph_type {
+            GlyphType::Bitmap => (FontTransform::identity(), (0.0, 0.0)),
+            GlyphType::Vector => {
+                (font.transform.invert_scale(y_scale, y_scale), font.get_subpx_offset(key))
+            }
         };
         if font.flags.contains(FontInstanceFlags::FLIP_X) {
             shape = shape.flip_x();
         }
         if font.flags.contains(FontInstanceFlags::FLIP_Y) {
             shape = shape.flip_y();
         }
         if font.flags.contains(FontInstanceFlags::TRANSPOSE) {
@@ -521,67 +536,36 @@ impl FontContext {
                 tx: 0.0,
                 ty: 0.0,
             })
         } else {
             None
         };
 
         let glyph = key.index() as CGGlyph;
-        let (strike_scale, pixel_step) = if bitmap { (y_scale, 1.0) } else { (x_scale, y_scale / x_scale) };
+        let (strike_scale, pixel_step) = if glyph_type == GlyphType::Bitmap {
+            (y_scale, 1.0)
+        } else {
+            (x_scale, y_scale / x_scale)
+        };
+
         let extra_strikes = font.get_extra_strikes(strike_scale / scale);
         let metrics = get_glyph_metrics(
             &ct_font,
             transform.as_ref(),
             glyph,
             x_offset,
             y_offset,
             extra_strikes as f64 * pixel_step,
         );
         if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
             return GlyphRasterResult::LoadFailed
         }
 
-        // The result of this function, in all render modes, is going to be a
-        // BGRA surface with white text on transparency using premultiplied
-        // alpha. For subpixel text, the RGB values will be the mask value for
-        // the individual components. For bitmap glyphs, the RGB values will be
-        // the (premultiplied) color of the pixel. For Alpha and Mono, each
-        // pixel will have R==G==B==A at the end of this function.
-        // We access the color channels in little-endian order.
-        // The CGContext will create and own our pixel buffer.
-        // In the non-Bitmap cases, we will ask CoreGraphics to draw text onto
-        // an opaque background. In order to hit the most efficient path in CG
-        // for this, we will tell CG that the CGContext is opaque, by passing
-        // an "[...]AlphaNone[...]" context flag. This creates a slight
-        // contradiction to the way we use the buffer after CG is done with it,
-        // because we will convert it into text-on-transparency. But that's ok;
-        // we still get four bytes per pixel and CG won't mess with the alpha
-        // channel after we've stopped calling CG functions. We just need to
-        // make sure that we don't look at the alpha values of the pixels that
-        // we get from CG, and compute our own alpha value only from RGB.
-        // Note that CG requires kCGBitmapByteOrder32Little in order to do
-        // subpixel AA at all (which we need it to do in both Subpixel and
-        // Alpha+smoothing mode). But little-endian is what we want anyway, so
-        // this works out nicely.
-        let context_flags = if bitmap {
-            kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst
-        } else {
-            kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst
-        };
-
-        let mut cg_context = CGContext::create_bitmap_context(
-            None,
-            metrics.rasterized_width as usize,
-            metrics.rasterized_height as usize,
-            8,
-            metrics.rasterized_width as usize * 4,
-            &CGColorSpace::create_device_rgb(),
-            context_flags,
-        );
+        let raster_size = Size2D::new(metrics.rasterized_width, metrics.rasterized_height);
 
         // If the font render mode is Alpha, we support two different ways to
         // compute the grayscale mask, depending on the value of the platform
         // options' font_smoothing flag:
         //  - Alpha + smoothing:
         //    We will recover a grayscale mask from a subpixel rasterization, in
         //    such a way that the result looks as close to subpixel text
         //    blending as we can make it. This involves gamma correction,
@@ -598,84 +582,102 @@ impl FontContext {
         // uses less font dilation (looks thinner) than dark text.
         // As a consequence, when we ask CG to rasterize with subpixel AA, we
         // will render white-on-black text as opposed to black-on-white text if
         // the text color brightness exceeds a certain threshold. This applies
         // to both the Subpixel and the "Alpha + smoothing" modes, but not to
         // the "Alpha without smoothing" and Mono modes.
         let use_white_on_black = should_use_white_on_black(font.color);
         let use_font_smoothing = font.flags.contains(FontInstanceFlags::FONT_SMOOTHING);
-        let (antialias, smooth, text_color, bg_color, bg_alpha, invert) = if bitmap {
-            (true, false, 0.0, 0.0, 0.0, false)
-        } else {
-            match (font.render_mode, use_font_smoothing) {
-                (FontRenderMode::Subpixel, _) |
-                (FontRenderMode::Alpha, true) => if use_white_on_black {
-                    (true, true, 1.0, 0.0, 1.0, false)
-                } else {
-                    (true, true, 0.0, 1.0, 1.0, true)
-                },
-                (FontRenderMode::Alpha, false) => (true, false, 0.0, 1.0, 1.0, true),
-                (FontRenderMode::Mono, _) => (false, false, 0.0, 1.0, 1.0, true),
+        let (antialias, smooth, text_color, bg_color, bg_alpha, invert) = match glyph_type {
+            GlyphType::Bitmap => (true, false, 0.0, 0.0, 0.0, false),
+            GlyphType::Vector => {
+                match (font.render_mode, use_font_smoothing) {
+                    (FontRenderMode::Subpixel, _) |
+                    (FontRenderMode::Alpha, true) => if use_white_on_black {
+                        (true, true, 1.0, 0.0, 1.0, false)
+                    } else {
+                        (true, true, 0.0, 1.0, 1.0, true)
+                    },
+                    (FontRenderMode::Alpha, false) => (true, false, 0.0, 1.0, 1.0, true),
+                    (FontRenderMode::Mono, _) => (false, false, 0.0, 1.0, 1.0, true),
+                }
             }
         };
 
-        // These are always true in Gecko, even for non-AA fonts
-        cg_context.set_allows_font_subpixel_positioning(true);
-        cg_context.set_should_subpixel_position_fonts(true);
+        {
+            let cg_context = self.graphics_context.get_context(&raster_size, glyph_type);
+
+            // These are always true in Gecko, even for non-AA fonts
+            cg_context.set_allows_font_subpixel_positioning(true);
+            cg_context.set_should_subpixel_position_fonts(true);
+
+            // Don't quantize because we're doing it already.
+            cg_context.set_allows_font_subpixel_quantization(false);
+            cg_context.set_should_subpixel_quantize_fonts(false);
+
+            cg_context.set_should_smooth_fonts(smooth);
+            cg_context.set_should_antialias(antialias);
 
-        // Don't quantize because we're doing it already.
-        cg_context.set_allows_font_subpixel_quantization(false);
-        cg_context.set_should_subpixel_quantize_fonts(false);
+            // Fill the background. This could be opaque white, opaque black, or
+            // transparency.
+            cg_context.set_rgb_fill_color(bg_color, bg_color, bg_color, bg_alpha);
+            let rect = CGRect {
+                origin: CGPoint { x: 0.0, y: 0.0 },
+                size: CGSize {
+                    width: metrics.rasterized_width as f64,
+                    height: metrics.rasterized_height as f64,
+                },
+            };
 
-        cg_context.set_should_smooth_fonts(smooth);
-        cg_context.set_should_antialias(antialias);
+            // Make sure we use the Copy blend mode, or else we'll get the Porter-Duff OVER
+            // operator, which can't clear to the transparent color!
+            cg_context.set_blend_mode(CGBlendMode::Copy);
+            cg_context.fill_rect(rect);
+            cg_context.set_blend_mode(CGBlendMode::Normal);
 
-        // Fill the background. This could be opaque white, opaque black, or
-        // transparency.
-        cg_context.set_rgb_fill_color(bg_color, bg_color, bg_color, bg_alpha);
-        let rect = CGRect {
-            origin: CGPoint { x: 0.0, y: 0.0 },
-            size: CGSize {
-                width: metrics.rasterized_width as f64,
-                height: metrics.rasterized_height as f64,
-            },
-        };
-        cg_context.fill_rect(rect);
+            // Set the text color and draw the glyphs.
+            cg_context.set_rgb_fill_color(text_color, text_color, text_color, 1.0);
+            cg_context.set_text_drawing_mode(CGTextDrawingMode::CGTextFill);
+
+            // CG Origin is bottom left, WR is top left. Need -y offset
+            let mut draw_origin = CGPoint {
+                x: -metrics.rasterized_left as f64 + x_offset,
+                y: metrics.rasterized_descent as f64 - y_offset,
+            };
+
+            if let Some(transform) = transform {
+                cg_context.set_text_matrix(&transform);
 
-        // Set the text color and draw the glyphs.
-        cg_context.set_rgb_fill_color(text_color, text_color, text_color, 1.0);
-        cg_context.set_text_drawing_mode(CGTextDrawingMode::CGTextFill);
+                draw_origin = draw_origin.apply_transform(&transform.invert());
+            } else {
+                // Make sure to reset this because some previous glyph rasterization might have
+                // changed it.
+                cg_context.set_text_matrix(&CG_AFFINE_TRANSFORM_IDENTITY);
+            }
 
-        // CG Origin is bottom left, WR is top left. Need -y offset
-        let mut draw_origin = CGPoint {
-            x: -metrics.rasterized_left as f64 + x_offset,
-            y: metrics.rasterized_descent as f64 - y_offset,
-        };
-
-        if let Some(transform) = transform {
-            cg_context.set_text_matrix(&transform);
-
-            draw_origin = draw_origin.apply_transform(&transform.invert());
+            if extra_strikes > 0 {
+                let strikes = 1 + extra_strikes;
+                let glyphs = vec![glyph; strikes];
+                let origins = (0..strikes).map(|i| {
+                    CGPoint {
+                        x: draw_origin.x + i as f64 * pixel_step,
+                        y: draw_origin.y,
+                    }
+                }).collect::<Vec<_>>();
+                ct_font.draw_glyphs(&glyphs, &origins, cg_context.clone());
+            } else {
+                ct_font.draw_glyphs(&[glyph], &[draw_origin], cg_context.clone());
+            }
         }
 
-        if extra_strikes > 0 {
-            let strikes = 1 + extra_strikes;
-            let glyphs = vec![glyph; strikes];
-            let origins = (0..strikes)
-                .map(|i| CGPoint { x: draw_origin.x + i as f64 * pixel_step, y: draw_origin.y })
-                .collect::<Vec<_>>();
-            ct_font.draw_glyphs(&glyphs, &origins, cg_context.clone());
-        } else {
-            ct_font.draw_glyphs(&[glyph], &[draw_origin], cg_context.clone());
-        }
+        let mut rasterized_pixels = self.graphics_context
+                                        .get_rasterized_pixels(&raster_size, glyph_type);
 
-        let mut rasterized_pixels = cg_context.data().to_vec();
-
-        if !bitmap {
+        if glyph_type == GlyphType::Vector {
             // We rendered text into an opaque surface. The code below needs to
             // ignore the current value of each pixel's alpha channel. But it's
             // allowed to write to the alpha channel, because we're done calling
             // CG functions now.
 
             if smooth {
                 // Convert to linear space for subpixel AA.
                 // We explicitly do not do this for grayscale AA ("Alpha without
@@ -717,21 +719,133 @@ impl FontContext {
             }
         }
 
         GlyphRasterResult::Bitmap(RasterizedGlyph {
             left: metrics.rasterized_left as f32,
             top: metrics.rasterized_ascent as f32,
             width: metrics.rasterized_width,
             height: metrics.rasterized_height,
-            scale: (if bitmap { scale / y_scale } else { scale }) as f32,
-            format: if bitmap { GlyphFormat::ColorBitmap } else { font.get_glyph_format() },
+            scale: match glyph_type {
+                GlyphType::Bitmap => (scale / y_scale) as f32,
+                GlyphType::Vector => scale as f32,
+            },
+            format: match glyph_type {
+                GlyphType::Bitmap => GlyphFormat::ColorBitmap,
+                GlyphType::Vector => font.get_glyph_format(),
+            },
             bytes: rasterized_pixels,
         })
     }
 }
 
 #[cfg(feature = "pathfinder")]
 impl<'a> Into<CGFont> for NativeFontHandleWrapper<'a> {
     fn into(self) -> CGFont {
         (self.0).0.clone()
     }
 }
+
+// Avoids taking locks by recycling Core Graphics contexts.
+#[allow(dead_code)]
+struct GraphicsContext {
+    vector_context: CGContext,
+    vector_context_size: Size2D<u32>,
+    bitmap_context: CGContext,
+    bitmap_context_size: Size2D<u32>,
+}
+
+impl GraphicsContext {
+    fn new() -> GraphicsContext {
+        let size = Size2D::new(INITIAL_CG_CONTEXT_SIDE_LENGTH, INITIAL_CG_CONTEXT_SIDE_LENGTH);
+        GraphicsContext {
+            vector_context: GraphicsContext::create_cg_context(&size, GlyphType::Vector),
+            vector_context_size: size,
+            bitmap_context: GraphicsContext::create_cg_context(&size, GlyphType::Bitmap),
+            bitmap_context_size: size,
+        }
+    }
+
+    #[allow(dead_code)]
+    fn get_context(&mut self, size: &Size2D<u32>, glyph_type: GlyphType)
+                   -> &mut CGContext {
+        let (cached_context, cached_size) = match glyph_type {
+            GlyphType::Vector => {
+                (&mut self.vector_context, &mut self.vector_context_size)
+            }
+            GlyphType::Bitmap => {
+                (&mut self.bitmap_context, &mut self.bitmap_context_size)
+            }
+        };
+        let rounded_size = Size2D::new(size.width.next_power_of_two(),
+                                       size.height.next_power_of_two());
+        if rounded_size.width > cached_size.width || rounded_size.height > cached_size.height {
+            *cached_size = Size2D::new(u32::max(cached_size.width, rounded_size.width),
+                                       u32::max(cached_size.height, rounded_size.height));
+            *cached_context = GraphicsContext::create_cg_context(cached_size, glyph_type);
+        }
+        cached_context
+    }
+
+    #[allow(dead_code)]
+    fn get_rasterized_pixels(&mut self, size: &Size2D<u32>, glyph_type: GlyphType)
+                             -> Vec<u8> {
+        let (cached_context, cached_size) = match glyph_type {
+            GlyphType::Vector => (&mut self.vector_context, &self.vector_context_size),
+            GlyphType::Bitmap => (&mut self.bitmap_context, &self.bitmap_context_size),
+        };
+        let cached_data = cached_context.data();
+        let cached_stride = cached_size.width as usize * 4;
+
+        let result_len = size.width as usize * size.height as usize * 4;
+        let mut result = Vec::with_capacity(result_len);
+        for y in (cached_size.height - size.height)..cached_size.height {
+            let cached_start = y as usize * cached_stride;
+            let cached_end = cached_start + size.width as usize * 4;
+            result.extend_from_slice(&cached_data[cached_start..cached_end]);
+        }
+        debug_assert_eq!(result.len(), result_len);
+        result
+    }
+
+    fn create_cg_context(size: &Size2D<u32>, glyph_type: GlyphType) -> CGContext {
+        // The result of rasterization, in all render modes, is going to be a
+        // BGRA surface with white text on transparency using premultiplied
+        // alpha. For subpixel text, the RGB values will be the mask value for
+        // the individual components. For bitmap glyphs, the RGB values will be
+        // the (premultiplied) color of the pixel. For Alpha and Mono, each
+        // pixel will have R==G==B==A at the end of this function.
+        // We access the color channels in little-endian order.
+        // The CGContext will create and own our pixel buffer.
+        // In the non-Bitmap cases, we will ask CoreGraphics to draw text onto
+        // an opaque background. In order to hit the most efficient path in CG
+        // for this, we will tell CG that the CGContext is opaque, by passing
+        // an "[...]AlphaNone[...]" context flag. This creates a slight
+        // contradiction to the way we use the buffer after CG is done with it,
+        // because we will convert it into text-on-transparency. But that's ok;
+        // we still get four bytes per pixel and CG won't mess with the alpha
+        // channel after we've stopped calling CG functions. We just need to
+        // make sure that we don't look at the alpha values of the pixels that
+        // we get from CG, and compute our own alpha value only from RGB.
+        // Note that CG requires kCGBitmapByteOrder32Little in order to do
+        // subpixel AA at all (which we need it to do in both Subpixel and
+        // Alpha+smoothing mode). But little-endian is what we want anyway, so
+        // this works out nicely.
+        let color_type = match glyph_type {
+            GlyphType::Vector => kCGImageAlphaNoneSkipFirst,
+            GlyphType::Bitmap => kCGImageAlphaPremultipliedFirst,
+        };
+
+        CGContext::create_bitmap_context(None,
+                                         size.width as usize,
+                                         size.height as usize,
+                                         8,
+                                         size.width as usize * 4,
+                                         &CGColorSpace::create_device_rgb(),
+                                         kCGBitmapByteOrder32Little | color_type)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+enum GlyphType {
+    Vector,
+    Bitmap,
+}
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -1302,16 +1302,21 @@ impl LazyInitializedDebugRenderer {
                     self.failed = true;
                 }
             }
         }
 
         self.debug_renderer.as_mut()
     }
 
+    /// Returns mut ref to `DebugRenderer` if one already exists, otherwise returns `None`.
+    pub fn try_get_mut<'a>(&'a mut self) -> Option<&'a mut DebugRenderer> {
+        self.debug_renderer.as_mut()
+    }
+
     pub fn deinit(self, device: &mut Device) {
         if let Some(debug_renderer) = self.debug_renderer {
             debug_renderer.deinit(device);
         }
     }
 }
 
 pub struct RendererVAOs {
@@ -2461,17 +2466,17 @@ impl Renderer {
         self.profile_counters.reset();
         self.profile_counters.frame_counter.inc();
 
         profile_timers.cpu_time.profile(|| {
             let _gm = self.gpu_profile.start_marker("end frame");
             self.gpu_profile.end_frame();
             #[cfg(feature = "debug_renderer")]
             {
-                if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
+                if let Some(debug_renderer) = self.debug.try_get_mut() {
                     debug_renderer.render(&mut self.device, framebuffer_size);
                 }
             }
             self.device.end_frame();
         });
         if framebuffer_size.is_some() {
             self.last_time = current_time;
         }
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.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 api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
-use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest};
+use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
 use api::{ClearCache, ColorF, DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
 use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
 use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
 use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
 use api::{GlyphDimensions, IdNamespace};
 use api::{ImageData, ImageDescriptor, ImageKey, ImageRendering};
 use api::{TileOffset, TileSize, TileRange, NormalizedRect, BlobImageData};
 use app_units::Au;
@@ -27,16 +27,17 @@ use glyph_rasterizer::{FontInstance, Gly
 use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use gpu_types::UvRectKind;
 use image::{compute_tile_range, for_each_tile_in_range};
 use internal_types::{FastHashMap, FastHashSet, SourceTexture, TextureUpdateList};
 use profiler::{ResourceProfileCounters, TextureCacheProfileCounters};
 use render_backend::FrameId;
 use render_task::{RenderTaskCache, RenderTaskCacheKey, RenderTaskId};
 use render_task::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle, RenderTaskTree};
+use smallvec::SmallVec;
 use std::collections::hash_map::Entry::{self, Occupied, Vacant};
 use std::collections::hash_map::ValuesMut;
 use std::{cmp, mem};
 use std::fmt::Debug;
 use std::hash::Hash;
 #[cfg(any(feature = "capture", feature = "replay"))]
 use std::path::PathBuf;
 use std::sync::{Arc, RwLock};
@@ -93,18 +94,19 @@ pub struct ImageProperties {
 #[derive(Debug, Copy, Clone, PartialEq)]
 enum State {
     Idle,
     AddResources,
     QueryResources,
 }
 
 /// Post scene building state.
-struct RasterizedBlobImage {
-    data: FastHashMap<Option<TileOffset>, BlobImageResult>,
+enum RasterizedBlob {
+    Tiled(FastHashMap<TileOffset, RasterizedBlobImage>),
+    NonTiled(Vec<RasterizedBlobImage>),
 }
 
 /// Pre scene building state.
 /// We use this to generate the async blob rendering requests.
 struct BlobImageTemplate {
     descriptor: ImageDescriptor,
     tiling: Option<TileSize>,
     dirty_rect: Option<DeviceUintRect>,
@@ -393,17 +395,17 @@ pub struct ResourceCache {
     glyph_rasterizer: GlyphRasterizer,
 
     // The set of images that aren't present or valid in the texture cache,
     // and need to be rasterized and/or uploaded this frame. This includes
     // both blobs and regular images.
     pending_image_requests: FastHashSet<ImageRequest>,
 
     blob_image_handler: Option<Box<BlobImageHandler>>,
-    rasterized_blob_images: FastHashMap<ImageKey, RasterizedBlobImage>,
+    rasterized_blob_images: FastHashMap<ImageKey, RasterizedBlob>,
     blob_image_templates: FastHashMap<ImageKey, BlobImageTemplate>,
 
     // If while building a frame we encounter blobs that we didn't already
     // rasterize, add them to this list and rasterize them synchronously.
     missing_blob_images: Vec<BlobImageParams>,
     // The rasterizer associated with the current scene.
     blob_image_rasterizer: Option<Box<AsyncBlobImageRasterizer>>,
 }
@@ -592,20 +594,50 @@ impl ResourceCache {
     }
 
     pub fn set_blob_rasterizer(&mut self, rasterizer: Box<AsyncBlobImageRasterizer>) {
         self.blob_image_rasterizer = Some(rasterizer);
     }
 
     pub fn add_rasterized_blob_images(&mut self, images: Vec<(BlobImageRequest, BlobImageResult)>) {
         for (request, result) in images {
+            let data = match result {
+                Ok(data) => data,
+                Err(..) => {
+                    warn!("Failed to rasterize a blob image");
+                    continue;
+                }
+            };
+
+            // First make sure we have an entry for this key (using a placeholder
+            // if need be).
             let image = self.rasterized_blob_images.entry(request.key).or_insert_with(
-                || { RasterizedBlobImage { data: FastHashMap::default() } }
+                || { RasterizedBlob::Tiled(FastHashMap::default()) }
             );
-            image.data.insert(request.tile, result);
+
+            if let Some(tile) = request.tile {
+                if let RasterizedBlob::NonTiled(..) = *image {
+                    *image = RasterizedBlob::Tiled(FastHashMap::default());
+                }
+
+                if let RasterizedBlob::Tiled(ref mut tiles) = *image {
+                    tiles.insert(tile, data);
+                }
+            } else {
+                if let RasterizedBlob::NonTiled(ref mut queue) = *image {
+                    // If our new rasterized rect overwrites items in the queue, discard them.
+                    queue.retain(|img| {
+                        !data.rasterized_rect.contains_rect(&img.rasterized_rect)
+                    });
+
+                    queue.push(data);
+                } else {
+                    *image = RasterizedBlob::NonTiled(vec![data]);
+                }
+            }
         }
     }
 
     pub fn add_font_template(&mut self, font_key: FontKey, template: FontTemplate) {
         // Push the new font to the font renderer, and also store
         // it locally for glyph metric requests.
         self.glyph_rasterizer.add_font(font_key, template.clone());
         self.resources.font_templates.insert(font_key, template);
@@ -920,19 +952,20 @@ impl ResourceCache {
         }
 
         if !self.pending_image_requests.insert(request) {
             return
         }
 
         if template.data.is_blob() {
             let request: BlobImageRequest = request.into();
-            let missing = match self.rasterized_blob_images.get(&request.key) {
-                Some(img) => !img.data.contains_key(&request.tile),
-                None => true,
+            let missing = match (self.rasterized_blob_images.get(&request.key), request.tile) {
+                (Some(RasterizedBlob::Tiled(tiles)), Some(tile)) => !tiles.contains_key(&tile),
+                (Some(RasterizedBlob::NonTiled(..)), None) => false,
+                _ => true,
             };
 
             // For some reason the blob image is missing. We'll fall back to
             // rasterizing it on the render backend thread.
             if missing {
                 let descriptor = match template.tiling {
                     Some(tile_size) => {
                         let tile = request.tile.unwrap();
@@ -1057,23 +1090,42 @@ impl ResourceCache {
                                 tile: Some(tile),
                             },
                             descriptor,
                             dirty_rect: None,
                         }
                     );
                 });
             } else {
-                let needs_upload = match self.cached_images.try_get(&key) {
+                let mut needs_upload = match self.cached_images.try_get(&key) {
                     Some(&ImageResult::UntiledAuto(ref entry)) => {
                         self.texture_cache.needs_upload(&entry.texture_cache_handle)
                     }
                     _ => true,
                 };
 
+                // If the queue of ratserized updates is growing it probably means that
+                // the texture is not getting uploaded because the display item is off-screen.
+                // In that case we are better off
+                // - Either not kicking rasterization for that image (avoid wasted cpu work
+                //   but will jank next time the item is visible because of lazy rasterization.
+                // - Clobber the update queue by pushing an update with a larger dirty rect
+                //   to prevent it from accumulating.
+                //
+                // We do the latter here but it's not ideal and might want to revisit and do
+                // the former instead.
+                match self.rasterized_blob_images.get(&key) {
+                    Some(RasterizedBlob::NonTiled(ref queue)) => {
+                        if queue.len() > 2 {
+                            needs_upload = true;
+                        }
+                    }
+                    _ => {},
+                };
+
                 let dirty_rect = if needs_upload {
                     // The texture cache entry has been evicted, treat it as all dirty.
                     None
                 } else {
                     template.dirty_rect
                 };
 
                 blob_request_params.push(
@@ -1109,38 +1161,29 @@ impl ResourceCache {
                 //println!("Missing image template (key={:?})!", key);
                 return;
             }
         };
         let tile_size = match template.tiling {
             Some(size) => size,
             None => { return; }
         };
-        let image = match self.rasterized_blob_images.get_mut(&key) {
-            Some(image) => image,
-            None => {
-                //println!("Missing rasterized blob (key={:?})!", key);
-                return;
-            }
+
+        let tiles = match self.rasterized_blob_images.get_mut(&key) {
+            Some(RasterizedBlob::Tiled(tiles)) => tiles,
+            _ => { return; }
         };
+
         let tile_range = compute_tile_range(
             &area,
             &template.descriptor.size,
             tile_size,
         );
-        image.data.retain(|tile, _| {
-            match *tile {
-                Some(offset) => tile_range.contains(&offset),
-                // This would be a bug. If we get here the blob should be tiled.
-                None => {
-                    error!("Blob image template and image data tiling don't match.");
-                    false
-                }
-            }
-        });
+
+        tiles.retain(|tile, _| { tile_range.contains(tile) });
     }
 
     pub fn request_glyphs(
         &mut self,
         mut font: FontInstance,
         glyph_keys: &[GlyphKey],
         gpu_cache: &mut GpuCache,
         render_task_tree: &mut RenderTaskTree,
@@ -1395,139 +1438,147 @@ impl ResourceCache {
         self.missing_blob_images.clear();
     }
 
     fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
         for request in self.pending_image_requests.drain() {
             let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
             debug_assert!(image_template.data.uses_texture_cache());
 
-            let mut blob_rasterized_rect = None;
-            let image_data = match image_template.data {
+            let mut updates: SmallVec<[(ImageData, Option<DeviceUintRect>); 1]> = SmallVec::new();
+
+            match image_template.data {
                 ImageData::Raw(..) | ImageData::External(..) => {
                     // Safe to clone here since the Raw image data is an
                     // Arc, and the external image data is small.
-                    image_template.data.clone()
+                    updates.push((image_template.data.clone(), None));
                 }
                 ImageData::Blob(..) => {
-                    let blob_image = self.rasterized_blob_images.get(&request.key).unwrap();
-                    match blob_image.data.get(&request.tile) {
-                        Some(result) => {
-                            let result = result
-                                .as_ref()
-                                .expect("Failed to render a blob image");
 
-                            // TODO: we may want to not panic and show a placeholder instead.
-
-                            blob_rasterized_rect = Some(result.rasterized_rect);
-
-                            ImageData::Raw(Arc::clone(&result.data))
+                    let blob_image = self.rasterized_blob_images.get_mut(&request.key).unwrap();
+                    match (blob_image, request.tile) {
+                        (RasterizedBlob::Tiled(ref tiles), Some(tile)) => {
+                            let img = &tiles[&tile];
+                            updates.push((
+                                ImageData::Raw(Arc::clone(&img.data)),
+                                Some(img.rasterized_rect)
+                            ));
                         }
-                        None => {
+                        (RasterizedBlob::NonTiled(ref mut queue), None) => {
+                            for img in queue.drain(..) {
+                                updates.push((
+                                    ImageData::Raw(img.data),
+                                    Some(img.rasterized_rect)
+                                ));
+                            }
+                        }
+                        _ =>  {
                             debug_assert!(false, "invalid blob image request during frame building");
                             continue;
                         }
                     }
                 }
             };
 
-            let entry = match *self.cached_images.get_mut(&request.key) {
-                ImageResult::UntiledAuto(ref mut entry) => entry,
-                ImageResult::Multi(ref mut entries) => entries.get_mut(&request.into()),
-                ImageResult::Err(_) => panic!("Update requested for invalid entry")
-            };
-
-            match (blob_rasterized_rect, entry.dirty_rect) {
-                (Some(rasterized), Some(dirty)) => {
-                    debug_assert!(request.tile.is_some() || rasterized.contains_rect(&dirty));
-                }
-                _ => {}
-            }
-
-            let mut descriptor = image_template.descriptor.clone();
-            let local_dirty_rect;
-
-            if let Some(tile) = request.tile {
-                let tile_size = image_template.tiling.unwrap();
-                let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
-
-                local_dirty_rect = if let Some(rect) = entry.dirty_rect.take() {
-                    // We should either have a dirty rect, or we are re-uploading where the dirty
-                    // rect is ignored anyway.
-                    let intersection = intersect_for_tile(rect, clipped_tile_size, tile_size, tile);
-                    debug_assert!(intersection.is_some() ||
-                                  self.texture_cache.needs_upload(&entry.texture_cache_handle));
-                    intersection
-                } else {
-                    None
+            for (image_data, blob_rasterized_rect) in updates {
+                let entry = match *self.cached_images.get_mut(&request.key) {
+                    ImageResult::UntiledAuto(ref mut entry) => entry,
+                    ImageResult::Multi(ref mut entries) => entries.get_mut(&request.into()),
+                    ImageResult::Err(_) => panic!("Update requested for invalid entry")
                 };
 
-                // The tiled image could be stored on the CPU as one large image or be
-                // already broken up into tiles. This affects the way we compute the stride
-                // and offset.
-                let tiled_on_cpu = image_template.data.is_blob();
-                if !tiled_on_cpu {
-                    let bpp = descriptor.format.bytes_per_pixel();
-                    let stride = descriptor.compute_stride();
-                    descriptor.stride = Some(stride);
-                    descriptor.offset +=
-                        tile.y as u32 * tile_size as u32 * stride +
-                        tile.x as u32 * tile_size as u32 * bpp;
+                let mut descriptor = image_template.descriptor.clone();
+                let mut local_dirty_rect;
+
+                if let Some(tile) = request.tile {
+                    let tile_size = image_template.tiling.unwrap();
+                    let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
+
+                    local_dirty_rect = if let Some(rect) = entry.dirty_rect.take() {
+                        // We should either have a dirty rect, or we are re-uploading where the dirty
+                        // rect is ignored anyway.
+                        let intersection = intersect_for_tile(rect, clipped_tile_size, tile_size, tile);
+                        debug_assert!(intersection.is_some() ||
+                                      self.texture_cache.needs_upload(&entry.texture_cache_handle));
+                        intersection
+                    } else {
+                        None
+                    };
+
+                    // The tiled image could be stored on the CPU as one large image or be
+                    // already broken up into tiles. This affects the way we compute the stride
+                    // and offset.
+                    let tiled_on_cpu = image_template.data.is_blob();
+                    if !tiled_on_cpu {
+                        let bpp = descriptor.format.bytes_per_pixel();
+                        let stride = descriptor.compute_stride();
+                        descriptor.stride = Some(stride);
+                        descriptor.offset +=
+                            tile.y as u32 * tile_size as u32 * stride +
+                            tile.x as u32 * tile_size as u32 * bpp;
+                    }
+
+                    descriptor.size = clipped_tile_size;
+                } else {
+                    local_dirty_rect = entry.dirty_rect.take();
                 }
 
-                descriptor.size = clipped_tile_size;
-            } else {
-                local_dirty_rect = entry.dirty_rect.take();
-            }
-
-            let filter = match request.rendering {
-                ImageRendering::Pixelated => {
-                    TextureFilter::Nearest
+                // If we are uploading the dirty region of a blob image we might have several
+                // rects to upload so we use each of these rasterized rects rather than the
+                // overall dirty rect of the image.
+                if blob_rasterized_rect.is_some() {
+                    local_dirty_rect = blob_rasterized_rect;
                 }
-                ImageRendering::Auto | ImageRendering::CrispEdges => {
-                    // If the texture uses linear filtering, enable mipmaps and
-                    // trilinear filtering, for better image quality. We only
-                    // support this for now on textures that are not placed
-                    // into the shared cache. This accounts for any image
-                    // that is > 512 in either dimension, so it should cover
-                    // the most important use cases. We may want to support
-                    // mip-maps on shared cache items in the future.
-                    if descriptor.allow_mipmaps &&
-                       descriptor.size.width > 512 &&
-                       descriptor.size.height > 512 &&
-                       !self.texture_cache.is_allowed_in_shared_cache(
-                        TextureFilter::Linear,
-                        &descriptor,
-                    ) {
-                        TextureFilter::Trilinear
-                    } else {
-                        TextureFilter::Linear
+
+                let filter = match request.rendering {
+                    ImageRendering::Pixelated => {
+                        TextureFilter::Nearest
                     }
-                }
-            };
-
-            let eviction = if image_template.data.is_blob() {
-                Eviction::Manual
-            } else {
-                Eviction::Auto
-            };
+                    ImageRendering::Auto | ImageRendering::CrispEdges => {
+                        // If the texture uses linear filtering, enable mipmaps and
+                        // trilinear filtering, for better image quality. We only
+                        // support this for now on textures that are not placed
+                        // into the shared cache. This accounts for any image
+                        // that is > 512 in either dimension, so it should cover
+                        // the most important use cases. We may want to support
+                        // mip-maps on shared cache items in the future.
+                        if descriptor.allow_mipmaps &&
+                           descriptor.size.width > 512 &&
+                           descriptor.size.height > 512 &&
+                           !self.texture_cache.is_allowed_in_shared_cache(
+                            TextureFilter::Linear,
+                            &descriptor,
+                        ) {
+                            TextureFilter::Trilinear
+                        } else {
+                            TextureFilter::Linear
+                        }
+                    }
+                };
 
-            //Note: at this point, the dirty rectangle is local to the descriptor space
-            self.texture_cache.update(
-                &mut entry.texture_cache_handle,
-                descriptor,
-                filter,
-                Some(image_data),
-                [0.0; 3],
-                local_dirty_rect,
-                gpu_cache,
-                None,
-                UvRectKind::Rect,
-                eviction,
-            );
+                let eviction = if image_template.data.is_blob() {
+                    Eviction::Manual
+                } else {
+                    Eviction::Auto
+                };
+
+                //Note: at this point, the dirty rectangle is local to the descriptor space
+                self.texture_cache.update(
+                    &mut entry.texture_cache_handle,
+                    descriptor,
+                    filter,
+                    Some(image_data),
+                    [0.0; 3],
+                    local_dirty_rect,
+                    gpu_cache,
+                    None,
+                    UvRectKind::Rect,
+                    eviction,
+                );
+            }
         }
     }
 
     pub fn end_frame(&mut self) {
         debug_assert_eq!(self.state, State::QueryResources);
         self.state = State::Idle;
     }
 
--- a/gfx/webrender/src/scene.rs
+++ b/gfx/webrender/src/scene.rs
@@ -53,32 +53,32 @@ impl SceneProperties {
     /// multiple set_properties and add_properties calls during a
     /// single transaction, and still correctly determine if any
     /// properties have changed. This can have significant power
     /// saving implications, allowing a frame build to be skipped
     /// if the properties haven't changed in many cases.
     pub fn flush_pending_updates(&mut self) -> bool {
         let mut properties_changed = false;
 
-        if let Some(pending_properties) = self.pending_properties.take() {
-            if pending_properties != self.current_properties {
+        if let Some(ref pending_properties) = self.pending_properties {
+            if *pending_properties != self.current_properties {
                 self.transform_properties.clear();
                 self.float_properties.clear();
 
                 for property in &pending_properties.transforms {
                     self.transform_properties
                         .insert(property.key.id, property.value);
                 }
 
                 for property in &pending_properties.floats {
                     self.float_properties
                         .insert(property.key.id, property.value);
                 }
 
-                self.current_properties = pending_properties;
+                self.current_properties = pending_properties.clone();
                 properties_changed = true;
             }
         }
 
         properties_changed
     }
 
     /// Get the current value for a transform property.
--- a/gfx/webrender_api/Cargo.toml
+++ b/gfx/webrender_api/Cargo.toml
@@ -21,12 +21,12 @@ ipc-channel = {version = "0.11.0", optio
 euclid = { version = "0.19", features = ["serde"] }
 serde = { version = "=1.0.66", features = ["rc"] }
 serde_derive = { version = "=1.0.66", features = ["deserialize_in_place"] }
 serde_bytes = "0.10"
 time = "0.1"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.6"
-core-graphics = "0.16"
+core-graphics = "0.17.1"
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.4.1"
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -22,11 +22,11 @@ version = "0.57.2"
 default-features = false
 features = ["capture", "serialize_program"]
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.4.1"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.6"
-core-graphics = "0.16"
+core-graphics = "0.17.1"
 foreign-types = "0.3.0"
 
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-f17f6a491d6ff3dc3e13e998dda788d8f5856338
+a601f9c291cee83257241ef61aaf62353c613438
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -83,21 +83,30 @@ enum class FontLCDFilter : uint8_t {
 enum class FontRenderMode : uint32_t {
   Mono = 0,
   Alpha,
   Subpixel,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
+// Specifies the format of a series of pixels, in driver terms.
 enum class ImageFormat : uint32_t {
+  // One-channel, byte storage. The "red" doesn't map to the color
+  // red per se, and is just the way that OpenGL has historically referred
+  // to single-channel buffers.
   R8 = 1,
+  // Four channels, byte storage.
   BGRA8 = 3,
+  // Four channels, float storage.
   RGBAF32 = 4,
+  // Two-channels, byte storage. Similar to `R8`, this just means
+  // "two channels" rather than "red and green".
   RG8 = 5,
+  // Four channels, signed integer storage.
   RGBAI32 = 6,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 enum class ImageRendering : uint32_t {
   Auto = 0,
   CrispEdges = 1,
@@ -595,16 +604,19 @@ struct ComplexClipRegion {
 
   bool operator==(const ComplexClipRegion& aOther) const {
     return rect == aOther.rect &&
            radii == aOther.radii &&
            mode == aOther.mode;
   }
 };
 
+// An opaque identifier describing an image registered with WebRender.
+// This is used as a handle to reference images, and is used as the
+// hash map key for the actual image storage in the `ResourceCache`.
 struct ImageKey {
   IdNamespace mNamespace;
   uint32_t mHandle;
 
   bool operator==(const ImageKey& aOther) const {
     return mNamespace == aOther.mNamespace &&
            mHandle == aOther.mHandle;
   }
--- a/gfx/wrench/Cargo.toml
+++ b/gfx/wrench/Cargo.toml
@@ -26,17 +26,17 @@ crossbeam = "0.2"
 osmesa-sys = { version = "0.1.2", optional = true }
 osmesa-src = { git = "https://github.com/jrmuizel/osmesa-src", optional = true, branch = "serialize" }
 webrender = {path = "../webrender", features=["capture","replay","debugger","png","profiler"]}
 webrender_api = {path = "../webrender_api", features=["serialize","deserialize"]}
 winit = "0.16"
 serde = {version = "1.0", features = ["derive"] }
 
 [target.'cfg(target_os = "macos")'.dependencies]
-core-graphics = "0.16"
+core-graphics = "0.17.1"
 core-foundation = "0.6"
 
 [features]
 headless = [ "osmesa-sys", "osmesa-src" ]
 pathfinder = [ "webrender/pathfinder" ]
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.4.1"
--- a/ipc/chromium/moz.build
+++ b/ipc/chromium/moz.build
@@ -90,26 +90,19 @@ if os_macosx:
         # This file cannot be built in unified mode because of the redefinition
         # of NoOp.
         'src/base/platform_thread_mac.mm',
     ]
 
 if os_bsd:
     SOURCES += [
         'src/base/atomicops_internals_x86_gcc.cc',
+        'src/base/process_util_linux.cc',
         'src/base/time_posix.cc',
     ]
-    if CONFIG['OS_ARCH'] == 'GNU_kFreeBSD':
-        SOURCES += [
-            'src/base/process_util_linux.cc'
-        ]
-    else:
-        SOURCES += [
-            'src/base/process_util_bsd.cc'
-        ]
 
 if os_linux:
     SOURCES += [
         'src/base/atomicops_internals_x86_gcc.cc',
         'src/base/process_util_linux.cc',
         'src/base/time_posix.cc',
     ]
     if CONFIG['OS_TARGET'] == 'Android':
--- a/ipc/chromium/src/base/process_util.h
+++ b/ipc/chromium/src/base/process_util.h
@@ -116,17 +116,17 @@ struct LaunchOptions {
 #if defined(OS_POSIX)
   environment_map env_map;
 
   // A mapping of (src fd -> dest fd) to propagate into the child
   // process.  All other fds will be closed, except std{in,out,err}.
   file_handle_mapping_vector fds_to_remap;
 #endif
 
-#if defined(OS_LINUX) || defined(OS_SOLARIS)
+#if defined(OS_LINUX)
   struct ForkDelegate {
     virtual ~ForkDelegate() { }
     virtual pid_t Fork() = 0;
   };
 
   // If non-null, the fork delegate will be called instead of fork().
   // It is not required to call pthread_atfork hooks.
   mozilla::UniquePtr<ForkDelegate> fork_delegate = nullptr;
deleted file mode 100644
--- a/ipc/chromium/src/base/process_util_bsd.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// derived from process_util_mac.cc
-
-#include "base/process_util.h"
-
-#include <fcntl.h>
-#include <spawn.h>
-#include <sys/wait.h>
-
-#include <string>
-
-#include "base/eintr_wrapper.h"
-
-namespace {
-
-static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
-
-}  // namespace
-
-namespace base {
-
-
-bool LaunchApp(const std::vector<std::string>& argv,
-               const LaunchOptions& options,
-               ProcessHandle* process_handle)
-{
-  bool retval = true;
-
-  char* argv_copy[argv.size() + 1];
-  for (size_t i = 0; i < argv.size(); i++) {
-    argv_copy[i] = const_cast<char*>(argv[i].c_str());
-  }
-  argv_copy[argv.size()] = NULL;
-
-  // Make sure we don't leak any FDs to the child process by marking all FDs
-  // as close-on-exec.
-  SetAllFDsToCloseOnExec();
-
-  EnvironmentArray vars = BuildEnvironmentArray(options.env_map);
-
-  posix_spawn_file_actions_t file_actions;
-  if (posix_spawn_file_actions_init(&file_actions) != 0) {
-    return false;
-  }
-
-  // Turn fds_to_remap array into a set of dup2 calls.
-  for (const auto& fd_map : options.fds_to_remap) {
-    int src_fd = fd_map.first;
-    int dest_fd = fd_map.second;
-
-    if (src_fd == dest_fd) {
-      int flags = fcntl(src_fd, F_GETFD);
-      if (flags != -1) {
-        fcntl(src_fd, F_SETFD, flags & ~FD_CLOEXEC);
-      }
-    } else {
-      if (posix_spawn_file_actions_adddup2(&file_actions, src_fd, dest_fd) != 0) {
-        posix_spawn_file_actions_destroy(&file_actions);
-        return false;
-      }
-    }
-  }
-
-  pid_t pid = 0;
-  int spawn_succeeded = (posix_spawnp(&pid,
-                                      argv_copy[0],
-                                      &file_actions,
-                                      NULL,
-                                      argv_copy,
-                                      vars.get()) == 0);
-
-  posix_spawn_file_actions_destroy(&file_actions);
-
-  bool process_handle_valid = pid > 0;
-  if (!spawn_succeeded || !process_handle_valid) {
-    retval = false;
-  } else {
-    gProcessLog.print("==> process %d launched child process %d\n",
-                      GetCurrentProcId(), pid);
-    if (options.wait)
-      HANDLE_EINTR(waitpid(pid, 0, 0));
-
-    if (process_handle)
-      *process_handle = pid;
-  }
-
-  return retval;
-}
-
-bool LaunchApp(const CommandLine& cl,
-               const LaunchOptions& options,
-               ProcessHandle* process_handle) {
-  return LaunchApp(cl.argv(), options, process_handle);
-}
-
-}  // namespace base
--- a/ipc/chromium/src/base/process_util_linux.cc
+++ b/ipc/chromium/src/base/process_util_linux.cc
@@ -11,16 +11,19 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
 #include "base/eintr_wrapper.h"
 #include "base/logging.h"
 #include "mozilla/ipc/FileDescriptorShuffle.h"
 #include "mozilla/UniquePtr.h"
 
+// WARNING: despite the name, this file is also used on the BSDs and
+// Solaris (basically, Unixes that aren't Mac OS), not just Linux.
+
 namespace {
 
 static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
 
 }  // namespace
 
 namespace base {
 
@@ -31,22 +34,26 @@ bool LaunchApp(const std::vector<std::st
   mozilla::UniquePtr<char*[]> argv_cstr(new char*[argv.size() + 1]);
 
   EnvironmentArray envp = BuildEnvironmentArray(options.env_map);
   mozilla::ipc::FileDescriptorShuffle shuffle;
   if (!shuffle.Init(options.fds_to_remap)) {
     return false;
   }
 
+#ifdef OS_LINUX
   pid_t pid = options.fork_delegate ? options.fork_delegate->Fork() : fork();
   // WARNING: if pid == 0, only async signal safe operations are permitted from
   // here until exec or _exit.
   //
   // Specifically, heap allocation is not safe: the sandbox's fork substitute
   // won't run the pthread_atfork handlers that fix up the malloc locks.
+#else
+  pid_t pid = fork();
+#endif
 
   if (pid < 0)
     return false;
 
   if (pid == 0) {
     // In the child:
     for (const auto& fds : shuffle.Dup2Sequence()) {
       if (HANDLE_EINTR(dup2(fds.first, fds.second)) != fds.second) {
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -444,19 +444,21 @@ with only_when('--enable-compile-environ
         if fuzzing and (afl or libfuzzer):
             return True
 
     set_config('FUZZING', enable_fuzzing)
     set_define('FUZZING', enable_fuzzing)
 
     set_config('LIBFUZZER', enable_libfuzzer)
     set_define('LIBFUZZER', enable_libfuzzer)
+    add_old_configure_assignment('LIBFUZZER', enable_libfuzzer)
 
     set_config('FUZZING_INTERFACES', enable_fuzzing_interfaces)
     set_define('FUZZING_INTERFACES', enable_fuzzing_interfaces)
+    add_old_configure_assignment('FUZZING_INTERFACES', enable_fuzzing_interfaces)
 
 # Enable pipeline operator
 # ===================================================
 js_option('--enable-pipeline-operator', default=False, help='Enable pipeline operator')
 
 @depends('--enable-pipeline-operator')
 def enable_pipeline_operator(value):
     if value:
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -438,17 +438,17 @@ dnl ====================================
 dnl GNU specific defaults
 dnl ========================================================
 if test "$GNU_CC"; then
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
         # symbols for shared objects in some cases.
-        if test -z "$MOZ_ASAN$MOZ_MSAN$MOZ_UBSAN$MOZ_TSAN"; then
+        if test -z "$MOZ_ASAN$MOZ_MSAN$MOZ_UBSAN$MOZ_TSAN$FUZZING_INTERFACES"; then
             # Don't allow undefined symbols in libraries
             DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
         fi
     fi
     WARNINGS_AS_ERRORS='-Werror'
     DSO_CFLAGS=''
 
     if test "$OS_ARCH" != "WINNT"; then
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -298,17 +298,17 @@ CookieServiceChild::RecvTrackCookiesLoad
 
 void
 CookieServiceChild::PrefChanged(nsIPrefBranch *aPrefBranch)
 {
   int32_t val;
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookieBehavior, &val)))
     mCookieBehavior =
       val >= nsICookieService::BEHAVIOR_ACCEPT &&
-      val <= nsICookieService::BEHAVIOR_LIMIT_FOREIGN
+      val <= nsICookieService::BEHAVIOR_LAST
         ? val : nsICookieService::BEHAVIOR_ACCEPT;
 
   bool boolval;
   if (NS_SUCCEEDED(aPrefBranch->GetBoolPref(kPrefThirdPartySession, &boolval)))
     mThirdPartySession = !!boolval;
 
   if (NS_SUCCEEDED(aPrefBranch->GetBoolPref(kPrefThirdPartyNonsecureSession,
                                             &boolval)))
--- a/old-configure.in
+++ b/old-configure.in
@@ -611,17 +611,17 @@ if test "$GNU_CC"; then
       ;;
     esac
 
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
         # symbols for shared objects in some cases.
-        if test -z "$MOZ_ASAN$MOZ_MSAN$MOZ_UBSAN$MOZ_TSAN"; then
+        if test -z "$MOZ_ASAN$MOZ_MSAN$MOZ_UBSAN$MOZ_TSAN$FUZZING_INTERFACES"; then
             # Don't allow undefined symbols in libraries
             DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
 
             # BSDs need `environ' exposed for posix_spawn (bug 753046)
             case "$OS_TARGET" in
             DragonFly|FreeBSD|NetBSD|OpenBSD)
                 if test -n "$HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED"; then
                     DSO_LDOPTS="$DSO_LDOPTS -Wl,--ignore-unresolved-symbol,environ"
--- a/third_party/rust/core-graphics/.cargo-checksum.json
+++ b/third_party/rust/core-graphics/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"b71b9a6f84b9263b2b89be6ec90dff5920ee68cf9e5768d73ed71957de2d0670","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"e191715db0c5bf37d5981f2a3b7ae5d0e53ab9cc39f2438d31e798b1fbf3ddec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"4a45abeb1e684e30bb361dfa7db59189423348e18d310cbae694b7c8c57cd86a","src/base.rs":"5faaadaf17d93c370a20f358be6c3f12958ab7d3f99ccc634421e28758fec88b","src/color_space.rs":"bada04ad391869474428070ad9ae5dbb5e7f5e03646226fab0b03e8e84240bfa","src/context.rs":"6cc8d083eea0d73ece30c1c405a74b43ca3f3a8f55917cdcd27c238a393f3de2","src/data_provider.rs":"258fef8d18ba4a79e7dbe7c23a41401924efa0c159e178f0bd9fa7c4ff9f131a","src/display.rs":"3ca38e1ff0200409c95941fcb64afa043310d1c0855c7614fd236c4f83e5a343","src/event.rs":"f2ade1c2c112bae7bc4f5df1eda63c13d1c32e5db255228f139ce17fb37c1a4b","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"63b7e50243a56254c800421df586abee59aead84f735f7df838ae04693aedf4b","src/geometry.rs":"b94e50a16b8540dc6f37bfe4b1549ac68974cd6ba6c0bbd9209559f8a46d86eb","src/image.rs":"40e744f28ef338b4c0138e05e0e191411518611bedb19deea2aa3a6e59f36567","src/lib.rs":"19d5e558cec5596d546f1753529a8e3cf951993f4500ee12fad0d7eb2dc86bc8","src/path.rs":"405032914ef806ac2d2e0ccda5987ed3176bfec0e2e8bd409b176a9c23f49885","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"27e00f7ad7645af05014f35939128833456cac766a2978c5da295c3757708a86"},"package":"92801c908ea6301ae619ed842a72e01098085fc321b9c2f3f833dad555bba055"}
\ No newline at end of file
+{"files":{".travis.yml":"b71b9a6f84b9263b2b89be6ec90dff5920ee68cf9e5768d73ed71957de2d0670","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"c30c4f657ed844adb3f412f758ce2bff9c62b83c8ec844cc447e24d785d18dba","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"4a45abeb1e684e30bb361dfa7db59189423348e18d310cbae694b7c8c57cd86a","src/base.rs":"5faaadaf17d93c370a20f358be6c3f12958ab7d3f99ccc634421e28758fec88b","src/color.rs":"b054b38b507733c8c3f5af981483c54836e8a7499a6d1a22244fb58312824acb","src/color_space.rs":"b3d7ee8a21703c789160867cb8eb2188bd1daa193e3d030f21adb6f1a6f872de","src/context.rs":"6b14ec712e5d0af4af6beb0cb1a998bf1262ec6ab6ad2b3efad9e0362ade83c9","src/data_provider.rs":"22614a6ce7f857dec33e6d2dc01261b71b1bc5d5609a54ee55e04c049670c072","src/display.rs":"5b04d1fded021fc1eecb89b6350a66f6668e802b51e75cf69892ca082257443c","src/event.rs":"f2ade1c2c112bae7bc4f5df1eda63c13d1c32e5db255228f139ce17fb37c1a4b","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"63b7e50243a56254c800421df586abee59aead84f735f7df838ae04693aedf4b","src/geometry.rs":"cdeb9624df601d235bcc34d46e35bea302079ce1e3668253356a618486693a9f","src/image.rs":"0af720ee020fb1c6a2f4b1ce49e3d27f8f21f0be6b81ba4b9c824f87564efa58","src/lib.rs":"03628fc67576f6948bb803a53fb147c520b264eaba684e37d26cd1b0197ebf30","src/path.rs":"c429afeaed999b02ac00f89a867b5fc64f1e223039079a4e0529306b734ff117","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"cc90b690f172da51a87ffb234f6e74a9f501c4f1630d7b51fa2d5846e80fc164"},"package":"62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"}
\ No newline at end of file
--- a/third_party/rust/core-graphics/Cargo.toml
+++ b/third_party/rust/core-graphics/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "core-graphics"
-version = "0.16.0"
+version = "0.17.1"
 authors = ["The Servo Project Developers"]
 description = "Bindings to Core Graphics for OS X"
 homepage = "https://github.com/servo/core-graphics-rs"
 license = "MIT / Apache-2.0"
 repository = "https://github.com/servo/core-foundation-rs"
 [dependencies.bitflags]
 version = "1.0"
 
new file mode 100644
--- /dev/null
+++ b/third_party/rust/core-graphics/src/color.rs
@@ -0,0 +1,33 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// 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 core_foundation::base::{CFTypeID};
+use base::CGFloat;
+use core_foundation::base::TCFType;
+use super::sys::{CGColorRef};
+
+declare_TCFType!{
+    CGColor, CGColorRef
+}
+impl_TCFType!(CGColor, CGColorRef, CGColorGetTypeID);
+
+impl CGColor {
+    pub fn rgb(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> Self {
+        unsafe { 
+            let ptr = CGColorCreateGenericRGB(red, green, blue, alpha);
+            CGColor::wrap_under_create_rule(ptr)
+        }
+    }
+}
+
+#[link(name = "CoreGraphics", kind = "framework")]
+extern {
+    fn CGColorCreateGenericRGB(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> ::sys::CGColorRef;
+    fn CGColorGetTypeID() -> CFTypeID;
+}
--- a/third_party/rust/core-graphics/src/color_space.rs
+++ b/third_party/rust/core-graphics/src/color_space.rs
@@ -29,31 +29,41 @@ impl CGColorSpace {
 
     pub fn create_with_name(name: CFStringRef) -> Option<CGColorSpace> {
         unsafe {
             let p = CGColorSpaceCreateWithName(name);
             if !p.is_null() {Some(CGColorSpace::from_ptr(p))} else {None}
         }
     }
 
+    #[inline]
     pub fn create_device_rgb() -> CGColorSpace {
         unsafe {
             let result = CGColorSpaceCreateDeviceRGB();
             CGColorSpace::from_ptr(result)
         }
     }
+
+    #[inline]
+    pub fn create_device_gray() -> CGColorSpace {
+        unsafe {
+            let result = CGColorSpaceCreateDeviceGray();
+            CGColorSpace::from_ptr(result)
+        }
+    }
 }
 
 #[link(name = "CoreGraphics", kind = "framework")]
 extern {
     pub static kCGColorSpaceSRGB: CFStringRef;
     pub static kCGColorSpaceAdobeRGB1998: CFStringRef;
     pub static kCGColorSpaceGenericGray: CFStringRef;
     pub static kCGColorSpaceGenericRGB: CFStringRef;
     pub static kCGColorSpaceGenericCMYK: CFStringRef;
     pub static kCGColorSpaceGenericRGBLinear: CFStringRef;
     pub static kCGColorSpaceGenericGrayGamma2_2: CFStringRef;
 
     fn CGColorSpaceCreateDeviceRGB() -> ::sys::CGColorSpaceRef;
+    fn CGColorSpaceCreateDeviceGray() -> ::sys::CGColorSpaceRef;
     fn CGColorSpaceCreateWithName(name: CFStringRef) -> ::sys::CGColorSpaceRef;
     fn CGColorSpaceGetTypeID() -> CFTypeID;
 }
 
--- a/third_party/rust/core-graphics/src/context.rs
+++ b/third_party/rust/core-graphics/src/context.rs
@@ -4,28 +4,64 @@
 // 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 base::CGFloat;
 use color_space::CGColorSpace;
-use core_foundation::base::{CFRelease, CFRetain, CFTypeID};
+use core_foundation::base::{ToVoid, CFRelease, CFRetain, CFTypeID};
 use font::{CGFont, CGGlyph};
 use geometry::CGPoint;
+use color::CGColor;
+use path::CGPathRef;
 use libc::{c_int, size_t};
 use std::os::raw::c_void;
 
 use std::cmp;
 use std::ptr;
 use std::slice;
 use geometry::{CGAffineTransform, CGRect};
 use image::CGImage;
-use foreign_types::ForeignType;
+use foreign_types::{ForeignType, ForeignTypeRef};
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub enum CGBlendMode {
+    Normal = 0,
+    Multiply,
+    Screen,
+    Overlay,
+    Darken,
+    Lighten,
+    ColorDodge,
+    ColorBurn,
+    SoftLight,
+    HardLight,
+    Difference,
+    Exclusion,
+    Hue,
+    Saturation,
+    Color,
+    Luminosity,
+    // 10.5 and up:
+    Clear,
+    Copy,
+    SourceIn,
+    SourceOut,
+    SourceAtop,
+    DestinationOver,
+    DestinationIn,
+    DestinationOut,
+    DestinationAtop,
+    Xor,
+    PlusDarker,
+    PlusLighter,
+}
 
 #[repr(C)]
 pub enum CGTextDrawingMode {
     CGTextFill,
     CGTextStroke,
     CGTextFillStroke,
     CGTextInvisible,
     CGTextFillClip,
@@ -72,16 +108,24 @@ impl CGContext {
 
     pub fn data(&mut self) -> &mut [u8] {
         unsafe {
             slice::from_raw_parts_mut(
                     CGBitmapContextGetData(self.as_ptr()) as *mut u8,
                     (self.height() * self.bytes_per_row()) as usize)
         }
     }
+}
+
+impl CGContextRef {
+    pub fn flush(&self) {
+        unsafe {
+            CGContextFlush(self.as_ptr())
+        }
+    }
 
     pub fn width(&self) -> size_t {
         unsafe {
             CGBitmapContextGetWidth(self.as_ptr())
         }
     }
 
     pub fn height(&self) -> size_t {
@@ -91,22 +135,40 @@ impl CGContext {
     }
 
     pub fn bytes_per_row(&self) -> size_t {
         unsafe {
             CGBitmapContextGetBytesPerRow(self.as_ptr())
         }
     }
 
+    pub fn set_fill_color(&self, color: &CGColor) {
+        unsafe {
+            CGContextSetFillColorWithColor(self.as_ptr(), color.to_void());
+        }
+    }
+
     pub fn set_rgb_fill_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
         unsafe {
             CGContextSetRGBFillColor(self.as_ptr(), red, green, blue, alpha)
         }
     }
 
+    pub fn set_gray_fill_color(&self, gray: CGFloat, alpha: CGFloat) {
+        unsafe {
+            CGContextSetGrayFillColor(self.as_ptr(), gray, alpha)
+        }
+    }
+
+    pub fn set_blend_mode(&self, blend_mode: CGBlendMode) {
+        unsafe {
+            CGContextSetBlendMode(self.as_ptr(), blend_mode)
+        }
+    }
+
     pub fn set_allows_font_smoothing(&self, allows_font_smoothing: bool) {
         unsafe {
             CGContextSetAllowsFontSmoothing(self.as_ptr(), allows_font_smoothing)
         }
     }
 
     pub fn set_font_smoothing_style(&self, style: i32) {
         unsafe {
@@ -157,16 +219,34 @@ impl CGContext {
     }
 
     pub fn set_text_drawing_mode(&self, mode: CGTextDrawingMode) {
         unsafe {
             CGContextSetTextDrawingMode(self.as_ptr(), mode)
         }
     }
 
+    pub fn add_path(&self, path: &CGPathRef) {
+        unsafe {
+            CGContextAddPath(self.as_ptr(), path.as_ptr());
+        }
+    }
+
+    pub fn close_path(&self) {
+        unsafe {
+            CGContextClosePath(self.as_ptr());
+        }
+    }
+
+    pub fn fill_path(&self) {
+        unsafe {
+            CGContextFillPath(self.as_ptr());
+        }
+    }
+
     pub fn fill_rect(&self, rect: CGRect) {
         unsafe {
             CGContextFillRect(self.as_ptr(), rect)
         }
     }
 
     pub fn draw_image(&self, rect: CGRect, image: &CGImage) {
         unsafe {
@@ -205,16 +285,40 @@ impl CGContext {
         unsafe {
             let count = cmp::min(glyphs.len(), positions.len());
             CGContextShowGlyphsAtPositions(self.as_ptr(),
                                            glyphs.as_ptr(),
                                            positions.as_ptr(),
                                            count)
         }
     }
+
+    pub fn save(&self) {
+        unsafe {
+            CGContextSaveGState(self.as_ptr());
+        }
+    }
+
+    pub fn restore(&self) {
+        unsafe {
+            CGContextRestoreGState(self.as_ptr());
+        }
+    }
+
+    pub fn translate(&self, tx: CGFloat, ty: CGFloat) {
+        unsafe {
+            CGContextTranslateCTM(self.as_ptr(), tx, ty);
+        }
+    }
+
+    pub fn scale(&self, sx: CGFloat, sy: CGFloat) {
+        unsafe {
+            CGContextScaleCTM(self.as_ptr(), sx, sy);
+        }
+    }
 }
 
 #[test]
 fn create_bitmap_context_test() {
     use geometry::*;
 
     let cs = CGColorSpace::create_device_rgb();
     let ctx = CGContext::create_bitmap_context(None,
@@ -247,39 +351,51 @@ extern {
                              bitmapInfo: u32)
                              -> ::sys::CGContextRef;
     fn CGBitmapContextGetData(context: ::sys::CGContextRef) -> *mut c_void;
     fn CGBitmapContextGetWidth(context: ::sys::CGContextRef) -> size_t;
     fn CGBitmapContextGetHeight(context: ::sys::CGContextRef) -> size_t;
     fn CGBitmapContextGetBytesPerRow(context: ::sys::CGContextRef) -> size_t;
     fn CGBitmapContextCreateImage(context: ::sys::CGContextRef) -> ::sys::CGImageRef;
     fn CGContextGetTypeID() -> CFTypeID;
+    fn CGContextFlush(c: ::sys::CGContextRef);
+    fn CGContextSetBlendMode(c: ::sys::CGContextRef, blendMode: CGBlendMode);
     fn CGContextSetAllowsFontSmoothing(c: ::sys::CGContextRef, allowsFontSmoothing: bool);
     fn CGContextSetShouldSmoothFonts(c: ::sys::CGContextRef, shouldSmoothFonts: bool);
     fn CGContextSetFontSmoothingStyle(c: ::sys::CGContextRef, style: c_int);
     fn CGContextSetAllowsAntialiasing(c: ::sys::CGContextRef, allowsAntialiasing: bool);
     fn CGContextSetShouldAntialias(c: ::sys::CGContextRef, shouldAntialias: bool);
     fn CGContextSetAllowsFontSubpixelQuantization(c: ::sys::CGContextRef,
                                                   allowsFontSubpixelQuantization: bool);
     fn CGContextSetShouldSubpixelQuantizeFonts(c: ::sys::CGContextRef,
                                                shouldSubpixelQuantizeFonts: bool);
     fn CGContextSetAllowsFontSubpixelPositioning(c: ::sys::CGContextRef,
                                                  allowsFontSubpixelPositioning: bool);
     fn CGContextSetShouldSubpixelPositionFonts(c: ::sys::CGContextRef,
                                                shouldSubpixelPositionFonts: bool);
     fn CGContextSetTextDrawingMode(c: ::sys::CGContextRef, mode: CGTextDrawingMode);
+    fn CGContextSetFillColorWithColor(c: ::sys::CGContextRef, color: *const c_void);
+    fn CGContextAddPath(c: ::sys::CGContextRef, path: ::sys::CGPathRef);
+    fn CGContextClosePath(c: ::sys::CGContextRef);
+    fn CGContextFillPath(c: ::sys::CGContextRef);
     fn CGContextSetRGBFillColor(context: ::sys::CGContextRef,
                                 red: CGFloat,
                                 green: CGFloat,
                                 blue: CGFloat,
                                 alpha: CGFloat);
+    fn CGContextSetGrayFillColor(context: ::sys::CGContextRef, gray: CGFloat, alpha: CGFloat);
     fn CGContextFillRect(context: ::sys::CGContextRef,
                          rect: CGRect);
     fn CGContextDrawImage(c: ::sys::CGContextRef, rect: CGRect, image: ::sys::CGImageRef);
     fn CGContextSetFont(c: ::sys::CGContextRef, font: ::sys::CGFontRef);
     fn CGContextSetFontSize(c: ::sys::CGContextRef, size: CGFloat);
     fn CGContextSetTextMatrix(c: ::sys::CGContextRef, t: CGAffineTransform);
     fn CGContextShowGlyphsAtPositions(c: ::sys::CGContextRef,
                                       glyphs: *const CGGlyph,
                                       positions: *const CGPoint,
                                       count: size_t);
+
+    fn CGContextSaveGState(c: ::sys::CGContextRef);
+    fn CGContextRestoreGState(c: ::sys::CGContextRef);
+    fn CGContextTranslateCTM(c: ::sys::CGContextRef, tx: CGFloat, ty: CGFloat);
+    fn CGContextScaleCTM(c: ::sys::CGContextRef, sx: CGFloat, sy: CGFloat);
 }
 
--- a/third_party/rust/core-graphics/src/data_provider.rs
+++ b/third_party/rust/core-graphics/src/data_provider.rs
@@ -67,25 +67,50 @@ impl CGDataProvider {
     /// Creates a data prvider from a given slice. The data provider does not own the slice in this
     /// case, so it's up to the user to ensure the memory safety here.
     pub unsafe fn from_slice(buffer: &[u8]) -> Self {
         let ptr = buffer.as_ptr() as *const c_void;
         let len = buffer.len() as size_t;
         let result = CGDataProviderCreateWithData(ptr::null_mut(), ptr, len, None);
         CGDataProvider::from_ptr(result)
     }
+
+    /// Creates a data provider from the given raw pointer, length, and destructor function.
+    ///
+    /// This is double-boxed because the Core Text API requires that the userdata be a single
+    /// pointer.
+    pub unsafe fn from_custom_data(custom_data: Box<Box<CustomData>>) -> Self {
+        let (ptr, len) = (custom_data.ptr() as *const c_void, custom_data.len());
+        let userdata = mem::transmute::<Box<Box<CustomData>>, &mut c_void>(custom_data);
+        let data_provider = CGDataProviderCreateWithData(userdata, ptr, len, Some(release));
+        return CGDataProvider::from_ptr(data_provider);
+
+        unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) {
+            drop(mem::transmute::<*mut c_void, Box<Box<CustomData>>>(info))
+        }
+    }
 }
 
 impl CGDataProviderRef {
     /// Creates a copy of the data from the underlying `CFDataProviderRef`.
     pub fn copy_data(&self) -> CFData {
         unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) }
     }
 }
 
+/// Encapsulates custom data that can be wrapped.
+pub trait CustomData {
+    /// Returns a pointer to the start of the custom data. This pointer *must not change* during
+    /// the lifespan of this CustomData.
+    unsafe fn ptr(&self) -> *const u8;
+    /// Returns the length of this custom data. This value must not change during the lifespan of
+    /// this CustomData.
+    unsafe fn len(&self) -> usize;
+}
+
 #[link(name = "CoreGraphics", kind = "framework")]
 extern {
     fn CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef;
     //fn CGDataProviderCreateDirect
     //fn CGDataProviderCreateSequential
     //fn CGDataProviderCreateWithCFData
     fn CGDataProviderCreateWithData(info: *mut c_void,
                                     data: *const c_void,
--- a/third_party/rust/core-graphics/src/display.rs
+++ b/third_party/rust/core-graphics/src/display.rs
@@ -6,19 +6,22 @@
 // <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.
 
 #![allow(non_upper_case_globals)]
 
 use libc;
 use std::ptr;
+use std::ops::Deref;
+
 pub use base::{CGError, boolean_t};
 pub use geometry::{CGRect, CGPoint, CGSize};
 
+use core_foundation::string::{CFString, CFStringRef};
 use core_foundation::base::{CFRetain, TCFType};
 use image::CGImage;
 use foreign_types::ForeignType;
 
 pub type CGDirectDisplayID = libc::uint32_t;
 pub type CGWindowID        = libc::uint32_t;
 
 pub const kCGNullWindowID: CGWindowID = 0 as CGWindowID;
@@ -37,21 +40,68 @@ pub type CGWindowImageOption = libc::uin
 
 pub const kCGWindowImageDefault: CGWindowImageOption = 0;
 pub const kCGWindowImageBoundsIgnoreFraming: CGWindowImageOption = 1 << 0;
 pub const kCGWindowImageShouldBeOpaque: CGWindowImageOption = 1 << 1;
 pub const kCGWindowImageOnlyShadows: CGWindowImageOption = 1 << 2;
 pub const kCGWindowImageBestResolution: CGWindowImageOption = 1 << 3;
 pub const kCGWindowImageNominalResolution: CGWindowImageOption = 1 << 4;
 
+pub const kDisplayModeValidFlag: u32               = 0x00000001;
+pub const kDisplayModeSafeFlag: u32                = 0x00000002;
+pub const kDisplayModeDefaultFlag: u32             = 0x00000004;
+pub const kDisplayModeAlwaysShowFlag: u32          = 0x00000008;
+pub const kDisplayModeNeverShowFlag: u32           = 0x00000080;
+pub const kDisplayModeNotResizeFlag: u32           = 0x00000010;
+pub const kDisplayModeRequiresPanFlag: u32         = 0x00000020;
+pub const kDisplayModeInterlacedFlag: u32          = 0x00000040;
+pub const kDisplayModeSimulscanFlag: u32           = 0x00000100;
+pub const kDisplayModeBuiltInFlag: u32             = 0x00000400;
+pub const kDisplayModeNotPresetFlag: u32           = 0x00000200;
+pub const kDisplayModeStretchedFlag: u32           = 0x00000800;
+pub const kDisplayModeNotGraphicsQualityFlag: u32  = 0x00001000;
+pub const kDisplayModeValidateAgainstDisplay: u32  = 0x00002000;
+pub const kDisplayModeTelevisionFlag: u32          = 0x00100000;
+pub const kDisplayModeValidForMirroringFlag: u32   = 0x00200000;
+pub const kDisplayModeAcceleratorBackedFlag: u32   = 0x00400000;
+pub const kDisplayModeValidForHiResFlag: u32       = 0x00800000;
+pub const kDisplayModeValidForAirPlayFlag: u32     = 0x01000000;
+pub const kDisplayModeNativeFlag: u32              = 0x02000000;
+
+pub const kDisplayModeSafetyFlags: u32             = 0x00000007;
+
+pub const IO1BitIndexedPixels: &str =     "P";
+pub const IO2BitIndexedPixels: &str =     "PP";
+pub const IO4BitIndexedPixels: &str =     "PPPP";
+pub const IO8BitIndexedPixels: &str =     "PPPPPPPP";
+pub const IO16BitDirectPixels: &str =     "-RRRRRGGGGGBBBBB";
+pub const IO32BitDirectPixels: &str =     "--------RRRRRRRRGGGGGGGGBBBBBBBB";
+pub const kIO30BitDirectPixels: &str =    "--RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB";
+pub const kIO64BitDirectPixels: &str =    "-16R16G16B16";
+pub const kIO16BitFloatPixels: &str =     "-16FR16FG16FB16";
+pub const kIO32BitFloatPixels: &str =     "-32FR32FG32FB32";
+pub const IOYUV422Pixels: &str =          "Y4U2V2";
+pub const IO8BitOverlayPixels: &str =     "O8";
+
+
 pub use core_foundation::dictionary::{ CFDictionary, CFDictionaryRef, CFDictionaryGetValueIfPresent };
 pub use core_foundation::array::{ CFArray, CFArrayRef };
 pub use core_foundation::array::{ CFArrayGetCount, CFArrayGetValueAtIndex };
 pub use core_foundation::base::{  CFIndex, CFRelease, CFTypeRef };
 
+pub type CGDisplayConfigRef = *mut libc::c_void;
+
+#[repr(u32)]
+#[derive(Clone, Copy)]
+pub enum CGConfigureOption {
+    ConfigureForAppOnly = 0,
+    ConfigureForSession = 1,
+    ConfigurePermanently = 2,
+}
+
 #[derive(Copy, Clone, Debug)]
 pub struct CGDisplay {
     pub id: CGDirectDisplayID,
 }
 
 foreign_type! {
     #[doc(hidden)]
     type CType = ::sys::CGDisplayMode;
@@ -87,16 +137,74 @@ impl CGDisplay {
             if !mode_ref.is_null() {
                 Some(CGDisplayMode::from_ptr(mode_ref))
             } else {
                 None
             }
         }
     }
 
+    /// Begins a new set of display configuration changes.
+    pub fn begin_configuration(&self) -> Result<CGDisplayConfigRef, CGError> {
+        unsafe {
+            let mut config_ref: CGDisplayConfigRef = ptr::null_mut();
+            let result = CGBeginDisplayConfiguration(&mut config_ref);
+            if result == 0 {
+                Ok(config_ref)
+            } else {
+                Err(result)
+            }
+        }
+    }
+
+    /// Cancels a set of display configuration changes.
+    pub fn cancel_configuration(&self, config_ref: &CGDisplayConfigRef) -> Result<(), CGError> {
+        let result = unsafe { CGCancelDisplayConfiguration(*config_ref) };
+        if result == 0 {
+            Ok(())
+        } else {
+            Err(result)
+        }
+    }
+
+    /// Completes a set of display configuration changes.
+    pub fn complete_configuration(
+        &self,
+        config_ref: &CGDisplayConfigRef,
+        option: CGConfigureOption,
+    ) -> Result<(), CGError> {
+        let result = unsafe { CGCompleteDisplayConfiguration(*config_ref, option) };
+        if result == 0 {
+            Ok(())
+        } else {
+            Err(result)
+        }
+    }
+
+    /// Configures the display mode of a display.
+    pub fn configure_display_with_display_mode(
+        &self,
+        config_ref: &CGDisplayConfigRef,
+        display_mode: &CGDisplayMode,
+    ) -> Result<(), CGError> {
+        let result = unsafe {
+            CGConfigureDisplayWithDisplayMode(
+                *config_ref,
+                self.id,
+                display_mode.as_ptr(),
+                ptr::null(),
+            )
+        };
+        if result == 0 {
+            Ok(())
+        } else {
+            Err(result)
+        }
+    }
+
     /// Returns an image containing the contents of the specified display.
     #[inline]
     pub fn image(&self) -> Option<CGImage> {
         unsafe {
             let image_ref = CGDisplayCreateImage(self.id);
             if !image_ref.is_null() {
                 Some(CGImage::from_ptr(image_ref))
             } else {
@@ -368,47 +476,116 @@ impl CGDisplay {
             Ok(())
         } else {
             Err(result)
         }
     }
 }
 
 impl CGDisplayMode {
+    /// Returns all display modes for the specified display id.
+    pub fn all_display_modes(
+        display_id: CGDirectDisplayID,
+        options: CFDictionaryRef,
+    ) -> Option<Vec<CGDisplayMode>> {
+        let array_opt: Option<CFArray> = unsafe {
+            let array_ref = CGDisplayCopyAllDisplayModes(display_id, options);
+            if array_ref != ptr::null() {
+                Some(CFArray::wrap_under_create_rule(array_ref))
+            } else {
+                None
+            }
+        };
+        match array_opt {
+            Some(modes) => {
+                let vec: Vec<CGDisplayMode> = modes
+                    .into_iter()
+                    .map(|value0| {
+                        let x = *value0.deref() as *mut ::sys::CGDisplayMode;
+                        unsafe { CGDisplayMode::from_ptr(x) }
+                    }).collect();
+                Some(vec)
+            }
+            None => None,
+        }
+    }
+
+    /// Returns the height of the specified display mode.
     #[inline]
     pub fn height(&self) -> u64 {
         unsafe { CGDisplayModeGetHeight(self.as_ptr()) as u64 }
     }
 
+    /// Returns the width of the specified display mode.
     #[inline]
     pub fn width(&self) -> u64 {
         unsafe { CGDisplayModeGetWidth(self.as_ptr()) as u64 }
     }
 
+    /// Returns the pixel height of the specified display mode.
     #[inline]
     pub fn pixel_height(&self) -> u64 {
         unsafe { CGDisplayModeGetPixelHeight(self.as_ptr()) as u64 }
     }
 
+    /// Returns the pixel width of the specified display mode.
     #[inline]
     pub fn pixel_width(&self) -> u64 {
         unsafe { CGDisplayModeGetPixelWidth(self.as_ptr()) as u64 }
     }
 
     #[inline]
     pub fn refresh_rate(&self) -> f64 {
         unsafe { CGDisplayModeGetRefreshRate(self.as_ptr()) }
     }
+
+    /// Returns the I/O Kit flags of the specified display mode.
+    #[inline]
+    pub fn io_flags(&self) -> u32 {
+        unsafe { CGDisplayModeGetIOFlags(self.as_ptr()) as u32 }
+    }
+
+    /// Returns the pixel encoding of the specified display mode.
+    #[inline]
+    pub fn pixel_encoding(&self) -> CFString {
+        unsafe { CFString::wrap_under_create_rule(CGDisplayModeCopyPixelEncoding(self.as_ptr())) }
+    }
+
+    /// Returns the number of bits per pixel of the specified display mode.
+    pub fn bit_depth(&self) -> usize {
+        let pixel_encoding = self.pixel_encoding().to_string();
+        // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels
+        // are made up and possibly non-sensical
+        if pixel_encoding.eq_ignore_ascii_case(kIO32BitFloatPixels) {
+            96
+        } else if pixel_encoding.eq_ignore_ascii_case(kIO64BitDirectPixels) {
+            64
+        } else if pixel_encoding.eq_ignore_ascii_case(kIO16BitFloatPixels) {
+            48
+        } else if pixel_encoding.eq_ignore_ascii_case(IO32BitDirectPixels) {
+            32
+        } else if pixel_encoding.eq_ignore_ascii_case(kIO30BitDirectPixels) {
+            30
+        } else if pixel_encoding.eq_ignore_ascii_case(IO16BitDirectPixels) {
+            16
+        } else if pixel_encoding.eq_ignore_ascii_case(IO8BitIndexedPixels) {
+            8
+        }else{
+            0
+        }
+    }
 }
 
 #[link(name = "CoreGraphics", kind = "framework")]
 extern "C" {
     pub static CGRectNull: CGRect;
     pub static CGRectInfinite: CGRect;
 
+    pub static kCGDisplayShowDuplicateLowResolutionModes: CFStringRef;
+
     pub fn CGDisplayModeRelease(mode: ::sys::CGDisplayModeRef);
 
     pub fn CGMainDisplayID() -> CGDirectDisplayID;
     pub fn CGDisplayIsActive(display: CGDirectDisplayID) -> boolean_t;
     pub fn CGDisplayIsAlwaysInMirrorSet(display: CGDirectDisplayID) -> boolean_t;
     pub fn CGDisplayIsAsleep(display: CGDirectDisplayID) -> boolean_t;
     pub fn CGDisplayIsBuiltin(display: CGDirectDisplayID) -> boolean_t;
     pub fn CGDisplayIsInHWMirrorSet(display: CGDirectDisplayID) -> boolean_t;
@@ -436,22 +613,42 @@ extern "C" {
         matching_display_count: *mut libc::uint32_t,
     ) -> CGError;
     pub fn CGDisplayModelNumber(display: CGDirectDisplayID) -> libc::uint32_t;
     pub fn CGDisplayPixelsHigh(display: CGDirectDisplayID) -> libc::size_t;
     pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t;
     pub fn CGDisplayBounds(display: CGDirectDisplayID) -> CGRect;
     pub fn CGDisplayCreateImage(display: CGDirectDisplayID) -> ::sys::CGImageRef;
 
+    pub fn CGBeginDisplayConfiguration(config: *const CGDisplayConfigRef) -> CGError;
+    pub fn CGCancelDisplayConfiguration(config: CGDisplayConfigRef) -> CGError;
+    pub fn CGCompleteDisplayConfiguration(
+        config: CGDisplayConfigRef,
+        option: CGConfigureOption,
+    ) -> CGError;
+    pub fn CGConfigureDisplayWithDisplayMode(
+        config: CGDisplayConfigRef,
+        display: CGDirectDisplayID,
+        mode: ::sys::CGDisplayModeRef,
+        options: CFDictionaryRef,
+    ) -> CGError;
+
     pub fn CGDisplayCopyDisplayMode(display: CGDirectDisplayID) -> ::sys::CGDisplayModeRef;
     pub fn CGDisplayModeGetHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t;
     pub fn CGDisplayModeGetWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t;
     pub fn CGDisplayModeGetPixelHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t;
     pub fn CGDisplayModeGetPixelWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t;
     pub fn CGDisplayModeGetRefreshRate(mode: ::sys::CGDisplayModeRef) -> libc::c_double;
+    pub fn CGDisplayModeGetIOFlags(mode: ::sys::CGDisplayModeRef) -> libc::uint32_t;
+    pub fn CGDisplayModeCopyPixelEncoding(mode: ::sys::CGDisplayModeRef) -> CFStringRef;
+
+    pub fn CGDisplayCopyAllDisplayModes(
+        display: CGDirectDisplayID,
+        options: CFDictionaryRef,
+    ) -> CFArrayRef;
 
     // mouse stuff
     pub fn CGDisplayHideCursor(display: CGDirectDisplayID) -> CGError;
     pub fn CGDisplayShowCursor(display: CGDirectDisplayID) -> CGError;
     pub fn CGDisplayMoveCursorToPoint(display: CGDirectDisplayID, point: CGPoint) -> CGError;
     pub fn CGWarpMouseCursorPosition(point: CGPoint) -> CGError;
     pub fn CGAssociateMouseAndMouseCursorPosition(connected: boolean_t) -> CGError;
 
--- a/third_party/rust/core-graphics/src/geometry.rs
+++ b/third_party/rust/core-graphics/src/geometry.rs
@@ -135,16 +135,25 @@ impl CGRect {
     #[inline]
     pub fn apply_transform(&self, t: &CGAffineTransform) -> CGRect {
         unsafe {
             ffi::CGRectApplyAffineTransform(*self, *t)
         }
     }
 }
 
+impl PartialEq for CGRect {
+    #[inline]
+    fn eq(&self, other: &CGRect) -> bool {
+        unsafe {
+            ffi::CGRectEqualToRect(*self, *other) != 0
+        }
+    }
+}
+
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Default)]
 pub struct CGAffineTransform {
     pub a: CGFloat,
     pub b: CGFloat,
     pub c: CGFloat,
     pub d: CGFloat,
     pub tx: CGFloat,
@@ -179,16 +188,17 @@ mod ffi {
 
     #[link(name = "CoreGraphics", kind = "framework")]
     extern {
         pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
         pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef,
                                                       rect: *mut CGRect) -> boolean_t;
         pub fn CGRectIsEmpty(rect: CGRect) -> boolean_t;
         pub fn CGRectIntersectsRect(rect1: CGRect, rect2: CGRect) -> boolean_t;
+        pub fn CGRectEqualToRect(rect1: CGRect, rect2: CGRect) -> boolean_t;
 
         pub fn CGAffineTransformInvert(t: CGAffineTransform) -> CGAffineTransform;
 
         pub fn CGPointApplyAffineTransform(point: CGPoint, t: CGAffineTransform) -> CGPoint;
         pub fn CGRectApplyAffineTransform(rect: CGRect, t: CGAffineTransform) -> CGRect;
         pub fn CGSizeApplyAffineTransform(size: CGSize, t: CGAffineTransform) -> CGSize;
     }
 }
--- a/third_party/rust/core-graphics/src/image.rs
+++ b/third_party/rust/core-graphics/src/image.rs
@@ -1,15 +1,16 @@
 use std::ptr;
 
 use base::CGFloat;
 use core_foundation::base::{CFRetain, CFTypeID};
 use core_foundation::data::CFData;
 use color_space::CGColorSpace;
 use data_provider::{CGDataProviderRef, CGDataProvider};
+use geometry::CGRect;
 use libc::size_t;
 use foreign_types::{ForeignType, ForeignTypeRef};
 
 #[repr(C)]
 pub enum CGImageAlphaInfo {
     CGImageAlphaNone, /* For example, RGB. */
     CGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */
     CGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
@@ -116,16 +117,27 @@ impl CGImageRef {
     /// Returns the raw image bytes wrapped in `CFData`. Note, the returned `CFData` owns the
     /// underlying buffer.
     pub fn data(&self) -> CFData {
         let data_provider = unsafe {
             CGDataProviderRef::from_ptr(CGImageGetDataProvider(self.as_ptr()))
         };
         data_provider.copy_data()
     }
+
+    /// Returns a cropped image. If the `rect` specifies a rectangle which lies outside of the
+    /// image bounds, the `None` is returned.
+    pub fn cropped(&self, rect: CGRect) -> Option<CGImage> {
+        let image_ptr = unsafe { CGImageCreateWithImageInRect(self.as_ptr(), rect) };
+        if !image_ptr.is_null() {
+            Some(unsafe { CGImage::from_ptr(image_ptr) })
+        } else {
+            None
+        }
+    }
 }
 
 #[link(name = "CoreGraphics", kind = "framework")]
 extern {
     fn CGImageGetTypeID() -> CFTypeID;
     fn CGImageGetWidth(image: ::sys::CGImageRef) -> size_t;
     fn CGImageGetHeight(image: ::sys::CGImageRef) -> size_t;
     fn CGImageGetBitsPerComponent(image: ::sys::CGImageRef) -> size_t;
@@ -141,12 +153,13 @@ extern {
                      bytesPerRow: size_t,
                      space: ::sys::CGColorSpaceRef,
                      bitmapInfo: u32,
                      provider: ::sys::CGDataProviderRef,
                      decode: *const CGFloat,
                      shouldInterpolate: bool,
                      intent: u32)
                      -> ::sys::CGImageRef;
+    fn CGImageCreateWithImageInRect(image: ::sys::CGImageRef, rect: CGRect) -> ::sys::CGImageRef;
 
     //fn CGImageGetAlphaInfo(image: ::sys::CGImageRef) -> CGImageAlphaInfo;
     //fn CGImageCreateCopyWithColorSpace(image: ::sys::CGImageRef, space: ::sys::CGColorSpaceRef) -> ::sys::CGImageRef
 }
--- a/third_party/rust/core-graphics/src/lib.rs
+++ b/third_party/rust/core-graphics/src/lib.rs
@@ -3,26 +3,29 @@
 //
 // 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.
 
 extern crate libc;
+
+#[macro_use]
 extern crate core_foundation;
 
 #[macro_use]
 #[cfg(target_os = "macos")]
 extern crate bitflags;
 
 #[macro_use]
 extern crate foreign_types;
 
 pub mod base;
+pub mod color;
 pub mod color_space;
 pub mod context;
 pub mod data_provider;
 #[cfg(target_os = "macos")]
 pub mod display;
 #[cfg(target_os = "macos")]
 pub mod event;
 #[cfg(target_os = "macos")]
--- a/third_party/rust/core-graphics/src/path.rs
+++ b/third_party/rust/core-graphics/src/path.rs
@@ -2,35 +2,48 @@
 // file at the top-level directory of this distribution.
 //
 // 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.
 
+pub use sys::CGPathRef as SysCGPathRef;
+
 use core_foundation::base::{CFRelease, CFRetain, CFTypeID};
 use foreign_types::ForeignType;
-use geometry::CGPoint;
-use std::os::raw::c_void;
+use geometry::{CGAffineTransform, CGPoint, CGRect};
+use libc::c_void;
 use std::fmt::{self, Debug, Formatter};
 use std::marker::PhantomData;
 use std::ops::Deref;
+use std::ptr;
 use std::slice;
 
 foreign_type! {
     #[doc(hidden)]
     type CType = ::sys::CGPath;
     fn drop = |p| CFRelease(p as *mut _);
     fn clone = |p| CFRetain(p as *const _) as *mut _;
     pub struct CGPath;
     pub struct CGPathRef;
 }
 
 impl CGPath {
+    pub fn from_rect(rect: CGRect, transform: Option<&CGAffineTransform>) -> CGPath {
+        unsafe {
+            let transform = match transform {
+                None => ptr::null(),
+                Some(transform) => transform as *const CGAffineTransform,
+            };
+            CGPath(CGPathCreateWithRect(rect, transform))
+        }
+    }
+
     pub fn type_id() -> CFTypeID {
         unsafe {
             CGPathGetTypeID()
         }
     }
 
     pub fn apply<'a, F>(&'a self, mut closure: &'a F) where F: FnMut(CGPathElementRef<'a>) {
         unsafe {
@@ -105,11 +118,12 @@ impl CGPathElement {
     }
 }
 
 type CGPathApplierFunction = unsafe extern "C" fn(info: *mut c_void,
                                                   element: *const CGPathElement);
 
 #[link(name = "CoreGraphics", kind = "framework")]
 extern {
+    fn CGPathCreateWithRect(rect: CGRect, transform: *const CGAffineTransform) -> ::sys::CGPathRef;
     fn CGPathApply(path: ::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction);
     fn CGPathGetTypeID() -> CFTypeID;
 }
--- a/third_party/rust/core-graphics/src/sys.rs
+++ b/third_party/rust/core-graphics/src/sys.rs
@@ -1,11 +1,18 @@
+use std::os::raw::c_void;
+
 pub enum CGImage {}
 pub type CGImageRef = *mut CGImage;
 
+#[repr(C)]
+pub struct __CGColor(c_void);
+
+pub type CGColorRef = *const __CGColor;
+
 pub enum CGColorSpace {}
 pub type CGColorSpaceRef = *mut CGColorSpace;
 
 pub enum CGPath {}
 pub type CGPathRef = *mut CGPath;
 
 pub enum CGDataProvider {}
 pub type CGDataProviderRef = *mut CGDataProvider;
--- a/third_party/rust/core-text/.cargo-checksum.json
+++ b/third_party/rust/core-text/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"671ed3c074224599fe05a7ab61a48c305842c9fc60e0dd486f4363bd4521fb8e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"1f747432402a00e7fc70227a5c0c49463638137fc804e2eb3c8fc74908b0875f","src/font_collection.rs":"e7e2facf1f5ec0661d61c230f84d6821e513315d7e311d2077443fb4e83c6f5d","src/font_descriptor.rs":"03439b11628c4aa5b8ac4aa68de25a2dd9da442755c0d91964170aca4a18c6d7","src/font_manager.rs":"de5e22620528322d6811d01f03975c53b676ec743297590de5e17a45393df0f1","src/lib.rs":"bd072cf53ebb643e4d21379d4487e60745999d20eab9caee8e56daa430cb65ca"},"package":"157ff38a92496dc676ce36d9124554e9ac66f1c1039f952690ac64f71cfa5968"}
\ No newline at end of file
+{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"73555748fd27f22bd31d4e17f95397ec4120e1a610b0d29333d750d8ecad228d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"f4094760cf28ad8c99a5fa427702008d0638abbc1d0adc02bc7f874744ff00dd","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"37b6af08ceaca9f15971ea009805bed00884294a035f152c617b43b333fdb471","src/font_manager.rs":"0abebafad90fc1cc74742493c812ec617a44a80969bab64807d6e32ae70033c0","src/lib.rs":"bd072cf53ebb643e4d21379d4487e60745999d20eab9caee8e56daa430cb65ca"},"package":"f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"}
\ No newline at end of file
--- a/third_party/rust/core-text/Cargo.toml
+++ b/third_party/rust/core-text/Cargo.toml
@@ -7,26 +7,26 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "core-text"
-version = "11.0.0"
+version = "13.0.0"
 authors = ["The Servo Project Developers"]
 description = "Bindings to the Core Text framework."
 license = "MIT/Apache-2.0"
 repository = "https://github.com/servo/core-foundation-rs"
 [dependencies.core-foundation]
 version = "0.6"
 
 [dependencies.core-graphics]
-version = "0.16"
+version = "0.17"
 
 [dependencies.foreign-types]
 version = "0.3"
 
 [dependencies.libc]
 version = "0.2"
 
 [features]
--- a/third_party/rust/core-text/src/font.rs
+++ b/third_party/rust/core-text/src/font.rs
@@ -158,16 +158,34 @@ impl CTFont {
             let font_ref = CTFontCreateCopyWithAttributes(self.0,
                                                           size as CGFloat,
                                                           ptr::null(),
                                                           ptr::null());
             CTFont::wrap_under_create_rule(font_ref)
         }
     }
 
+    pub fn clone_with_symbolic_traits(&self,
+                                      trait_value: CTFontSymbolicTraits,
+                                      trait_mask: CTFontSymbolicTraits)
+                                      -> Option<CTFont> {
+        unsafe {
+            let font_ref = CTFontCreateCopyWithSymbolicTraits(self.0,
+                                                              0.0,
+                                                              ptr::null(),
+                                                              trait_value,
+                                                              trait_mask);
+            if font_ref.is_null() {
+                None
+            } else {
+                Some(CTFont::wrap_under_create_rule(font_ref))
+            }
+        }
+    }
+
     // Names
     pub fn family_name(&self) -> String {
         unsafe {
             let value = get_string_by_name_key(self, kCTFontFamilyNameKey);
             value.expect("Fonts should always have a family name.")
         }
     }
 
@@ -187,16 +205,30 @@ impl CTFont {
 
     pub fn postscript_name(&self) -> String {
         unsafe {
             let value = get_string_by_name_key(self, kCTFontPostScriptNameKey);
             value.expect("Fonts should always have a PostScript name.")
         }
     }
 
+    pub fn display_name(&self) -> String {
+        unsafe {
+            let value = get_string_by_name_key(self, kCTFontFullNameKey);
+            value.expect("Fonts should always have a PostScript name.")
+        }
+    }
+
+    pub fn style_name(&self) -> String {
+        unsafe {
+            let value = get_string_by_name_key(self, kCTFontStyleNameKey);
+            value.expect("Fonts should always have a style name.")
+        }
+    }
+
     pub fn all_traits(&self) -> CTFontTraits {
         unsafe {
             CTFontTraits::wrap_under_create_rule(CTFontCopyTraits(self.0))
         }
     }
 
     // Font metrics
     pub fn ascent(&self) -> CGFloat {
@@ -218,16 +250,28 @@ impl CTFont {
     }
 
     pub fn underline_position(&self) -> CGFloat {
         unsafe {
             CTFontGetUnderlinePosition(self.0)
         }
     }
 
+    pub fn slant_angle(&self) -> CGFloat {
+        unsafe {
+            CTFontGetSlantAngle(self.0)
+        }
+    }
+
+    pub fn cap_height(&self) -> CGFloat {
+        unsafe {
+            CTFontGetCapHeight(self.0)
+        }
+    }
+
     pub fn bounding_box(&self) -> CGRect {
         unsafe {
             CTFontGetBoundingBox(self.0)
         }
     }
 
     pub fn leading(&self) -> CGFloat {
         unsafe {
@@ -248,32 +292,43 @@ impl CTFont {
     }
 
     pub fn pt_size(&self) -> CGFloat {
         unsafe {
             CTFontGetSize(self.0)
         }
     }
 
-    pub fn get_glyphs_for_characters(&self, characters: *const UniChar, glyphs: *mut CGGlyph, count: CFIndex)
-                                     -> bool {
-        unsafe {
-            CTFontGetGlyphsForCharacters(self.0, characters, glyphs, count)
-        }
+    pub unsafe fn get_glyphs_for_characters(&self,
+                                            characters: *const UniChar,
+                                            glyphs: *mut CGGlyph,
+                                            count: CFIndex)
+                                            -> bool {
+        CTFontGetGlyphsForCharacters(self.0, characters, glyphs, count)
     }
 
-    pub fn get_advances_for_glyphs(&self,
-                                   orientation: CTFontOrientation,
-                                   glyphs: *const CGGlyph,
-                                   advances: *mut CGSize,
-                                   count: CFIndex)
-                                   -> f64 {
-        unsafe {
-            CTFontGetAdvancesForGlyphs(self.0, orientation, glyphs, advances, count) as f64
-        }
+    pub unsafe fn get_advances_for_glyphs(&self,
+                                          orientation: CTFontOrientation,
+                                          glyphs: *const CGGlyph,
+                                          advances: *mut CGSize,
+                                          count: CFIndex)
+                                          -> f64 {
+        CTFontGetAdvancesForGlyphs(self.0, orientation, glyphs, advances, count) as f64
+    }
+
+    pub unsafe fn get_vertical_translations_for_glyphs(&self,
+                                                       orientation: CTFontOrientation,
+                                                       glyphs: *const CGGlyph,
+                                                       translations: *mut CGSize,
+                                                       count: CFIndex) {
+        CTFontGetVerticalTranslationsForGlyphs(self.0,
+                                               orientation,
+                                               glyphs,
+                                               translations,
+                                               count)
     }
 
     pub fn get_font_table(&self, tag: u32) -> Option<CFData> {
         unsafe {
             let result = CTFontCopyTable(self.0,
                                          tag as CTFontTableTag,
                                          kCTFontTableOptionsExcludeSynthetic);
             if result.is_null() {
@@ -333,16 +388,23 @@ impl CTFont {
             let path = CTFontCreatePathForGlyph(self.0, glyph, matrix);
             if path.is_null() {
                 Err(())
             } else {
                 Ok(CGPath::from_ptr(path))
             }
         }
     }
+
+    #[inline]
+    pub fn glyph_count(&self) -> CFIndex {
+        unsafe {
+            CTFontGetGlyphCount(self.0)
+        }
+    }
 }
 
 // Helper methods
 fn get_string_by_name_key(font: &CTFont, name_key: CFStringRef) -> Option<String> {
     unsafe {
         let result = CTFontCopyName(font.as_concrete_TypeRef(), name_key);
         if result.is_null() {
             None
@@ -372,17 +434,17 @@ pub fn debug_font_traits(font: &CTFont) 
     println!("kCTFontItalicTrait: {}", sym.is_italic());
     println!("kCTFontBoldTrait: {}", sym.is_bold());
     println!("kCTFontExpandedTrait: {}", sym.is_expanded());
     println!("kCTFontCondensedTrait: {}", sym.is_condensed());
     println!("kCTFontMonoSpaceTrait: {}", sym.is_monospace());
 
     let traits = font.all_traits();
     println!("kCTFontWeightTrait: {}", traits.normalized_weight());
-//    println!("kCTFontWidthTrait: {}", traits.normalized_width());
+    println!("kCTFontWidthTrait: {}", traits.normalized_width());
 //    println!("kCTFontSlantTrait: {}", traits.normalized_slant());
 }
 
 #[cfg(feature = "mountainlion")]
 pub fn cascade_list_for_languages(font: &CTFont, language_pref_list: &CFArray<CFString>) -> CFArray<CTFontDescriptor> {
     unsafe {
         let font_collection_ref =
             CTFontCopyDefaultCascadeListForLanguages(font.as_concrete_TypeRef(),
@@ -441,17 +503,22 @@ extern {
     fn CTFontCreateWithName(name: CFStringRef, size: CGFloat, matrix: *const CGAffineTransform) -> CTFontRef;
     //fn CTFontCreateWithNameAndOptions
     fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat,
                                       matrix: *const CGAffineTransform) -> CTFontRef;
     //fn CTFontCreateWithFontDescriptorAndOptions
     //fn CTFontCreateUIFontForLanguage
     fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform,
                                       attributes: CTFontDescriptorRef) -> CTFontRef;
-    //fn CTFontCreateCopyWithSymbolicTraits
+    fn CTFontCreateCopyWithSymbolicTraits(font: CTFontRef,
+                                          size: CGFloat,
+                                          matrix: *const CGAffineTransform,
+                                          symTraitValue: CTFontSymbolicTraits,
+                                          symTraitMask: CTFontSymbolicTraits)
+                                          -> CTFontRef;
     //fn CTFontCreateCopyWithFamily
     //fn CTFontCreateForString
 
     /* Getting Font Data */
     //fn CTFontCopyFontDescriptor(font: CTFontRef) -> CTFontDescriptorRef;
     fn CTFontCopyAttribute(font: CTFontRef, attribute: CFStringRef) -> CFTypeRef;
     fn CTFontGetSize(font: CTFontRef) -> CGFloat;
     //fn CTFontGetMatrix
@@ -475,36 +542,45 @@ extern {
     //fn CTFontGetStringEncoding
     //fn CTFontCopySupportedLanguages
 
     /* Getting Font Metrics */
     fn CTFontGetAscent(font: CTFontRef) -> CGFloat;
     fn CTFontGetDescent(font: CTFontRef) -> CGFloat;
     fn CTFontGetLeading(font: CTFontRef) -> CGFloat;
     fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
-    //fn CTFontGetGlyphCount
+    fn CTFontGetGlyphCount(font: CTFontRef) -> CFIndex;
     fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
     fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat;
     fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat;
-    //fn CTFontGetSlantAngle
-    //fn CTFontGetCapHeight
+    fn CTFontGetSlantAngle(font: CTFontRef) -> CGFloat;
+    fn CTFontGetCapHeight(font: CTFontRef) -> CGFloat;
     fn CTFontGetXHeight(font: CTFontRef) -> CGFloat;
 
     /* Getting Glyph Data */
     fn CTFontCreatePathForGlyph(font: CTFontRef, glyph: CGGlyph, matrix: *const CGAffineTransform)
                                 -> CGPathRef;
     //fn CTFontGetGlyphWithName
     fn CTFontGetBoundingRectsForGlyphs(font: CTFontRef,
                                        orientation: CTFontOrientation,
                                        glyphs: *const CGGlyph,
                                        boundingRects: *mut CGRect,
                                        count: CFIndex)
                                        -> CGRect;
-    fn CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *const CGGlyph, advances: *mut CGSize, count: CFIndex) -> libc::c_double;
-    //fn CTFontGetVerticalTranslationsForGlyphs
+    fn CTFontGetAdvancesForGlyphs(font: CTFontRef,
+                                  orientation: CTFontOrientation,
+                                  glyphs: *const CGGlyph,
+                                  advances: *mut CGSize,
+                                  count: CFIndex)
+                                  -> libc::c_double;
+    fn CTFontGetVerticalTranslationsForGlyphs(font: CTFontRef,
+                                              orientation: CTFontOrientation,
+                                              glyphs: *const CGGlyph,
+                                              translations: *mut CGSize,
+                                              count: CFIndex);
 
     /* Working With Font Variations */
     fn CTFontCopyVariationAxes(font: CTFontRef) -> CFArrayRef;
     //fn CTFontCopyVariation
 
     /* Getting Font Features */
     //fn CTFontCopyFeatures
     //fn CTFontCopyFeatureSettings
--- a/third_party/rust/core-text/src/font_collection.rs
+++ b/third_party/rust/core-text/src/font_collection.rs
@@ -28,21 +28,27 @@ pub type CTFontCollectionRef = *const __
 declare_TCFType! {
     CTFontCollection, CTFontCollectionRef
 }
 impl_TCFType!(CTFontCollection, CTFontCollectionRef, CTFontCollectionGetTypeID);
 impl_CFTypeDescription!(CTFontCollection);
 
 
 impl CTFontCollection {
-    pub fn get_descriptors(&self) -> CFArray<CTFontDescriptor> {
+    pub fn get_descriptors(&self) -> Option<CFArray<CTFontDescriptor>> {
         // surprise! this function follows the Get rule, despite being named *Create*.
         // So we have to addRef it to avoid CTFontCollection from double freeing it later.
         unsafe {
-            CFArray::wrap_under_get_rule(CTFontCollectionCreateMatchingFontDescriptors(self.0))
+            let font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(self.0);
+            if font_descriptors.is_null() {
+                // This returns null if there are no matching font descriptors.
+                None
+            } else {
+                Some(CFArray::wrap_under_get_rule(font_descriptors))
+            }
         }
     }
 }
 
 pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection {
     unsafe {
         let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
         let value = CFNumber::from(1i64);
--- a/third_party/rust/core-text/src/font_descriptor.rs
+++ b/third_party/rust/core-text/src/font_descriptor.rs
@@ -48,24 +48,26 @@ pub const kCTFontColorGlyphsTrait: CTFon
 pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = (15 << kCTFontClassMaskShift );
 
 pub trait SymbolicTraitAccessors {
     fn is_italic(&self) -> bool;
     fn is_bold(&self) -> bool;
     fn is_expanded(&self) -> bool;
     fn is_condensed(&self) -> bool;
     fn is_monospace(&self) -> bool;
+    fn is_vertical(&self) -> bool;
 }
 
 impl SymbolicTraitAccessors for CTFontSymbolicTraits {
     fn is_italic(&self) -> bool { (*self & kCTFontItalicTrait) != 0 }
     fn is_bold(&self) -> bool { (*self & kCTFontBoldTrait) != 0 }
     fn is_expanded(&self) -> bool { (*self & kCTFontExpandedTrait) != 0 }
     fn is_condensed(&self) -> bool { (*self & kCTFontCondensedTrait) != 0 }
     fn is_monospace(&self) -> bool { (*self & kCTFontMonoSpaceTrait) != 0 }
+    fn is_vertical(&self) -> bool { (*self & kCTFontVerticalTrait) != 0 }
 }
 
 pub type CTFontStylisticClass = u32;
 pub const kCTFontUnknownClass: CTFontStylisticClass = (0 << kCTFontClassMaskShift );
 pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = (1 << kCTFontClassMaskShift );
 pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = (2 << kCTFontClassMaskShift );
 pub const kCTFontModernSerifsClass: CTFontStylisticClass = (3 << kCTFontClassMaskShift );
 pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = (4 << kCTFontClassMaskShift );
--- a/third_party/rust/core-text/src/font_manager.rs
+++ b/third_party/rust/core-text/src/font_manager.rs
@@ -2,19 +2,27 @@
 // file at the top-level directory of this distribution.
 //
 // 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 core_foundation::array::CFArrayRef;
+use core_foundation::array::{CFArray, CFArrayRef};
+use core_foundation::base::TCFType;
+use core_foundation::string::CFString;
 use core_foundation::url::CFURLRef;
 
+pub fn copy_available_font_family_names() -> CFArray<CFString> {
+    unsafe {
+        TCFType::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames())
+    }
+}
+
 extern {
     /*
      * CTFontManager.h
      */
 
     // Incomplete function bindings are mostly related to CoreText font matching, which
     // we implement in a platform-independent manner using FontMatcher.
 
--- a/tools/fuzzing/libfuzzer-flags.mozbuild
+++ b/tools/fuzzing/libfuzzer-flags.mozbuild
@@ -1,13 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 libfuzzer_flags = []
 
-if CONFIG['HAVE_LIBFUZZER_FLAG_FUZZER_NO_LINK']:
-    libfuzzer_flags += ['-fsanitize=fuzzer-no-link']
-else:
-    # Older Clang versions (<= 5) only support an older set of libFuzzer flags
-    libfuzzer_flags += ['-fsanitize-coverage=trace-pc-guard,trace-cmp']
+if CONFIG['LIBFUZZER_FLAGS']:
+    libfuzzer_flags += CONFIG['LIBFUZZER_FLAGS']
+