merge autoland to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 25 Apr 2017 11:23:43 +0200
changeset 354748 a30dc237c3a600a5231f2974fc2b85dfb5513414
parent 354747 ac529a874366e1f3c3040490fe5eaf8089cd8874 (current diff)
parent 354719 a12d2e2fb05a5f04a446939f6c332780911fd37e (diff)
child 354749 92d204a15eb315424736d945d24475aed752b1a6
child 354888 ac924d6a49eb0331941a1dc73d7557f48739f847
child 354903 4c552f9aa3dd87bbd3937f6c0e31a1507da67b3f
child 355359 0fd98cd60c05480d81c3f7d48d017535b8bbd1c0
push id41424
push usercbook@mozilla.com
push dateTue, 25 Apr 2017 09:53:59 +0000
treeherderautoland@92d204a15eb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.0a1
first release with
nightly linux32
a30dc237c3a6 / 55.0a1 / 20170425101243 / files
nightly linux64
a30dc237c3a6 / 55.0a1 / 20170425101537 / files
nightly mac
a30dc237c3a6 / 55.0a1 / 20170425030221 / files
nightly win32
a30dc237c3a6 / 55.0a1 / 20170425030221 / files
nightly win64
a30dc237c3a6 / 55.0a1 / 20170425030221 / 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 autoland to mozilla-central a=merge
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -244,16 +244,35 @@ button {
 }
 
 .addon-target-container .name {
   align-self: center;
   font-size: 16px;
   font-weight: 600;
 }
 
+.addon-target-info {
+  display: grid;
+  font-size: 14px;
+  grid-template-columns: 128px 1fr;
+}
+
+.addon-target-info-label {
+  padding-inline-end: 8px;
+  padding-bottom: 8px;
+}
+
+.addon-target-info-label:last-of-type {
+  padding-bottom: 16px;
+}
+
+.addon-target-info-content {
+  margin: 0;
+}
+
 .addon-target-button {
   background: none;
   border: none;
   color: #0087ff;
   font-size: 14px;
   margin: 12px;
   min-width: auto;
   padding: 4px;
@@ -284,8 +303,23 @@ button {
   text-decoration: none;
 }
 
 .addon-target-button:first-of-type {
   /* Subtract the start padding so the button is still a bigger click target but
    * lines up with the icon. */
   margin-inline-start: -4px;
 }
+
+/* We want the ellipsis on the left-hand-side, so make the parent RTL
+ * with an ellipsis and the child can be LTR. */
+.file-path {
+  direction: rtl;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.file-path-inner {
+  direction: ltr;
+  unicode-bidi: plaintext;
+}
--- a/devtools/client/aboutdebugging/components/addons/panel.js
+++ b/devtools/client/aboutdebugging/components/addons/panel.js
@@ -71,17 +71,18 @@ module.exports = createClass({
     this.props.client.listAddons()
       .then(({addons}) => {
         let extensions = addons.filter(addon => addon.debuggable).map(addon => {
           return {
             name: addon.name,
             icon: addon.iconURL || ExtensionIcon,
             addonID: addon.id,
             addonActor: addon.actor,
-            temporarilyInstalled: addon.temporarilyInstalled
+            temporarilyInstalled: addon.temporarilyInstalled,
+            url: addon.url,
           };
         });
 
         this.setState({ extensions });
       }, error => {
         throw new Error("Client error while listing addons: " + error);
       });
   },
--- a/devtools/client/aboutdebugging/components/addons/target.js
+++ b/devtools/client/aboutdebugging/components/addons/target.js
@@ -15,28 +15,48 @@ loader.lazyImporter(this, "BrowserToolbo
   "resource://devtools/client/framework/ToolboxProcess.jsm");
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/main", true);
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
+function filePathForTarget(target) {
+  // Only show file system paths, and only for temporarily installed add-ons.
+  if (!target.temporarilyInstalled || !target.url || !target.url.startsWith("file://")) {
+    return [];
+  }
+  let path = target.url.slice("file://".length);
+  return [
+    dom.dt(
+      { className: "addon-target-info-label" },
+      Strings.GetStringFromName("location")),
+    // Wrap the file path in a span so we can do some RTL/LTR swapping to get
+    // the ellipsis on the left.
+    dom.dd(
+      { className: "addon-target-info-content file-path" },
+      dom.span({ className: "file-path-inner", title: path }, path),
+    ),
+  ];
+}
+
 module.exports = createClass({
   displayName: "AddonTarget",
 
   propTypes: {
     client: PropTypes.instanceOf(DebuggerClient).isRequired,
     debugDisabled: PropTypes.bool,
     target: PropTypes.shape({
       addonActor: PropTypes.string.isRequired,
       addonID: PropTypes.string.isRequired,
       icon: PropTypes.string,
       name: PropTypes.string.isRequired,
-      temporarilyInstalled: PropTypes.bool
+      temporarilyInstalled: PropTypes.bool,
+      url: PropTypes.string,
     }).isRequired
   },
 
   debug() {
     let { target } = this.props;
     debugAddon(target.addonID);
   },
 
@@ -63,16 +83,20 @@ module.exports = createClass({
       dom.div({ className: "target" },
         dom.img({
           className: "target-icon",
           role: "presentation",
           src: target.icon
         }),
         dom.span({ className: "target-name", title: target.name }, target.name)
       ),
+      dom.dl(
+        { className: "addon-target-info" },
+        ...filePathForTarget(target),
+      ),
       dom.div({className: "addon-target-actions"},
         dom.button({
           className: "debug-button addon-target-button",
           onClick: this.debug,
           disabled: debugDisabled,
         }, Strings.GetStringFromName("debug")),
         dom.button({
           className: "reload-button addon-target-button",
--- a/devtools/client/aboutdebugging/test/browser.ini
+++ b/devtools/client/aboutdebugging/test/browser.ini
@@ -15,16 +15,17 @@ support-files =
   service-workers/empty-sw.js
   service-workers/fetch-sw.html
   service-workers/fetch-sw.js
   service-workers/push-sw.html
   service-workers/push-sw.js
   !/devtools/client/framework/test/shared-head.js
 
 [browser_addons_debug_bootstrapped.js]
+[browser_addons_debug_info.js]
 [browser_addons_debug_webextension.js]
 tags = webextensions
 [browser_addons_debug_webextension_inspector.js]
 tags = webextensions
 [browser_addons_debug_webextension_nobg.js]
 tags = webextensions
 [browser_addons_debug_webextension_popup.js]
 tags = webextensions
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
@@ -0,0 +1,28 @@
+"use strict";
+
+const ADDON_ID = "test-devtools@mozilla.org";
+const ADDON_NAME = "test-devtools";
+
+add_task(function* () {
+  let { tab, document } = yield openAboutDebugging("addons");
+  yield waitForInitialAddonList(document);
+
+  yield installAddon({
+    document,
+    path: "addons/unpacked/install.rdf",
+    name: ADDON_NAME,
+  });
+
+  let container = document.querySelector(`[data-addon-id="${ADDON_ID}"]`);
+  let filePath = container.querySelector(".file-path");
+  let expectedFilePath = "browser/devtools/client/aboutdebugging/test/addons/unpacked/";
+
+  // Verify that the path to the install location is shown next to its label.
+  ok(filePath, "file path is in DOM");
+  ok(filePath.textContent.endsWith(expectedFilePath), "file path is set correctly");
+  is(filePath.previousElementSibling.textContent, "Location", "file path has label");
+
+  yield uninstallAddon({document, id: ADDON_ID, name: ADDON_NAME});
+
+  yield closeAboutDebugging(tab);
+});
--- a/devtools/client/commandline/test/browser_cmd_qsa.js
+++ b/devtools/client/commandline/test/browser_cmd_qsa.js
@@ -1,33 +1,33 @@
-/* Any copyright is dedicated to the Public Domain.
-* http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Tests that the qsa commands work as they should.
-
-const TEST_URI = "data:text/html;charset=utf-8,<body></body>";
-
-function test() {
-  helpers.addTabWithToolbar(TEST_URI, function (options) {
-    return helpers.audit(options, [
-      {
-        setup: "qsa",
-        check: {
-          input:  "qsa",
-          hints:  " [query]",
-          markup: "VVV",
-          status: "VALID"
-        }
-      },
-      {
-        setup: "qsa body",
-        check: {
-          input:  "qsa body",
-          hints:  "",
-          markup: "VVVVVVVV",
-          status: "VALID"
-        }
-      }
-    ]);
-  }).then(finish, helpers.handleError);
-}
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the qsa commands work as they should.
+
+const TEST_URI = "data:text/html;charset=utf-8,<body></body>";
+
+function test() {
+  helpers.addTabWithToolbar(TEST_URI, function (options) {
+    return helpers.audit(options, [
+      {
+        setup: "qsa",
+        check: {
+          input:  "qsa",
+          hints:  " [query]",
+          markup: "VVV",
+          status: "VALID"
+        }
+      },
+      {
+        setup: "qsa body",
+        check: {
+          input:  "qsa body",
+          hints:  "",
+          markup: "VVVVVVVV",
+          status: "VALID"
+        }
+      }
+    ]);
+  }).then(finish, helpers.handleError);
+}
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-cancel.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-cancel.js
@@ -1,58 +1,58 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Make sure that canceling a name change correctly unhides the separator and
- * value elements.
- */
-
-const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html";
-
-function test() {
-  Task.spawn(function* () {
+
+/**
+ * Make sure that canceling a name change correctly unhides the separator and
+ * value elements.
+ */
+
+const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html";
+
+function test() {
+  Task.spawn(function* () {
     let options = {
       source: TAB_URL,
       line: 1
     };
-    let [tab,, panel] = yield initDebugger(TAB_URL, options);
-    let win = panel.panelWin;
-    let vars = win.DebuggerView.Variables;
-
-    win.DebuggerView.WatchExpressions.addExpression("this");
-
-    callInTab(tab, "ermahgerd");
-    yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS);
-
-    let exprScope = vars.getScopeAtIndex(0);
-    let {target} = exprScope.get("this");
-
-    let name = target.querySelector(".title > .name");
-    let separator = target.querySelector(".separator");
-    let value = target.querySelector(".value");
-
-    is(separator.hidden, false,
-      "The separator element should not be hidden.");
-    is(value.hidden, false,
-      "The value element should not be hidden.");
-
-    for (let key of ["ESCAPE", "RETURN"]) {
-      EventUtils.sendMouseEvent({ type: "dblclick" }, name, win);
-
-      is(separator.hidden, true,
-        "The separator element should be hidden.");
-      is(value.hidden, true,
-        "The value element should be hidden.");
-
-      EventUtils.sendKey(key, win);
-
-      is(separator.hidden, false,
-        "The separator element should not be hidden.");
-      is(value.hidden, false,
-        "The value element should not be hidden.");
-    }
-
-    yield resumeDebuggerThenCloseAndFinish(panel);
-  });
-}
+    let [tab,, panel] = yield initDebugger(TAB_URL, options);
+    let win = panel.panelWin;
+    let vars = win.DebuggerView.Variables;
+
+    win.DebuggerView.WatchExpressions.addExpression("this");
+
+    callInTab(tab, "ermahgerd");
+    yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS);
+
+    let exprScope = vars.getScopeAtIndex(0);
+    let {target} = exprScope.get("this");
+
+    let name = target.querySelector(".title > .name");
+    let separator = target.querySelector(".separator");
+    let value = target.querySelector(".value");
+
+    is(separator.hidden, false,
+      "The separator element should not be hidden.");
+    is(value.hidden, false,
+      "The value element should not be hidden.");
+
+    for (let key of ["ESCAPE", "RETURN"]) {
+      EventUtils.sendMouseEvent({ type: "dblclick" }, name, win);
+
+      is(separator.hidden, true,
+        "The separator element should be hidden.");
+      is(value.hidden, true,
+        "The value element should be hidden.");
+
+      EventUtils.sendKey(key, win);
+
+      is(separator.hidden, false,
+        "The separator element should not be hidden.");
+      is(value.hidden, false,
+        "The value element should not be hidden.");
+    }
+
+    yield resumeDebuggerThenCloseAndFinish(panel);
+  });
+}
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-popup-17.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-popup-17.js
@@ -1,80 +1,80 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Tests opening the variable inspection popup while stopped at a debugger statement,
- * clicking "step in" and verifying that the popup is gone.
- */
-
-const TAB_URL = EXAMPLE_URL + "doc_with-frame.html";
-
-let gTab, gPanel, gDebugger;
-let actions, gSources, gVariables;
-
-function test() {
-  let options = {
-    source: TAB_URL,
-    line: 1
-  };
-  initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
-    gTab = aTab;
-    gPanel = aPanel;
-    gDebugger = gPanel.panelWin;
-    actions = bindActionCreators(gPanel);
-    gSources = gDebugger.DebuggerView.Sources;
-    gVariables = gDebugger.DebuggerView.Variables;
-    let bubble = gDebugger.DebuggerView.VariableBubble;
-    let tooltip = bubble._tooltip.panel;
-    let testPopupHiding = Task.async(function* () {
-      yield addBreakpoint();
-      yield ensureThreadClientState(gPanel, "resumed");
-      yield pauseDebuggee();
-      yield openVarPopup(gPanel, { line: 20, ch: 17 });
-      is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
-          "The popup should be open with a simple text entry");
-      // Now we're stopped at a breakpoint with an open popup
-      // we'll send a keypress and check if the popup closes
-      executeSoon(() => EventUtils.synthesizeKey("VK_F11", {}));
-      // The keypress should cause one resumed event and one paused event
-      yield waitForThreadEvents(gPanel, "resumed");
-      yield waitForThreadEvents(gPanel, "paused");
-      // Here's the state we're actually interested in checking..
-      checkVariablePopupClosed(bubble);
-      yield resumeDebuggerThenCloseAndFinish(gPanel);
-    });
-    testPopupHiding();
-  });
-}
-
-function addBreakpoint() {
-  return actions.addBreakpoint({ actor: gSources.selectedValue, line: 21 });
-}
-
-function pauseDebuggee() {
-  generateMouseClickInTab(gTab, "content.document.querySelector('button')");
-
-  // The first 'with' scope should be expanded by default, but the
-  // variables haven't been fetched yet. This is how 'with' scopes work.
-  return promise.all([
-    waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
-    waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
-  ]);
-}
-
-function checkVariablePopupClosed(bubble) {
-  ok(!bubble.contentsShown(),
-    "When stepping, popup should close and be hidden.");
-  ok(bubble._tooltip.isEmpty(),
-    "The variable inspection popup should now be empty.");
-  ok(!bubble._markedText,
-    "The marked text in the editor was removed.");
-}
-
-registerCleanupFunction(function () {
-  gTab = null;
-  gPanel = null;
-  gDebugger = null;
-  actions = null;
-  gSources = null;
-  gVariables = null;
-});
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests opening the variable inspection popup while stopped at a debugger statement,
+ * clicking "step in" and verifying that the popup is gone.
+ */
+
+const TAB_URL = EXAMPLE_URL + "doc_with-frame.html";
+
+let gTab, gPanel, gDebugger;
+let actions, gSources, gVariables;
+
+function test() {
+  let options = {
+    source: TAB_URL,
+    line: 1
+  };
+  initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
+    gTab = aTab;
+    gPanel = aPanel;
+    gDebugger = gPanel.panelWin;
+    actions = bindActionCreators(gPanel);
+    gSources = gDebugger.DebuggerView.Sources;
+    gVariables = gDebugger.DebuggerView.Variables;
+    let bubble = gDebugger.DebuggerView.VariableBubble;
+    let tooltip = bubble._tooltip.panel;
+    let testPopupHiding = Task.async(function* () {
+      yield addBreakpoint();
+      yield ensureThreadClientState(gPanel, "resumed");
+      yield pauseDebuggee();
+      yield openVarPopup(gPanel, { line: 20, ch: 17 });
+      is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
+          "The popup should be open with a simple text entry");
+      // Now we're stopped at a breakpoint with an open popup
+      // we'll send a keypress and check if the popup closes
+      executeSoon(() => EventUtils.synthesizeKey("VK_F11", {}));
+      // The keypress should cause one resumed event and one paused event
+      yield waitForThreadEvents(gPanel, "resumed");
+      yield waitForThreadEvents(gPanel, "paused");
+      // Here's the state we're actually interested in checking..
+      checkVariablePopupClosed(bubble);
+      yield resumeDebuggerThenCloseAndFinish(gPanel);
+    });
+    testPopupHiding();
+  });
+}
+
+function addBreakpoint() {
+  return actions.addBreakpoint({ actor: gSources.selectedValue, line: 21 });
+}
+
+function pauseDebuggee() {
+  generateMouseClickInTab(gTab, "content.document.querySelector('button')");
+
+  // The first 'with' scope should be expanded by default, but the
+  // variables haven't been fetched yet. This is how 'with' scopes work.
+  return promise.all([
+    waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
+    waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
+  ]);
+}
+
+function checkVariablePopupClosed(bubble) {
+  ok(!bubble.contentsShown(),
+    "When stepping, popup should close and be hidden.");
+  ok(bubble._tooltip.isEmpty(),
+    "The variable inspection popup should now be empty.");
+  ok(!bubble._markedText,
+    "The marked text in the editor was removed.");
+}
+
+registerCleanupFunction(function () {
+  gTab = null;
+  gPanel = null;
+  gDebugger = null;
+  actions = null;
+  gSources = null;
+  gVariables = null;
+});
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -74,16 +74,20 @@ selectAddonFromFile2 = Select Manifest F
 # This string is displayed as a label of the button that reloads a given addon.
 reload = Reload
 
 # LOCALIZATION NOTE (reloadDisabledTooltip):
 # This string is displayed in a tooltip that appears when hovering over a
 # disabled 'reload' button.
 reloadDisabledTooltip = Only temporarily installed add-ons can be reloaded
 
+# LOCALIZATION NOTE (location):
+# This string is displayed as a label for the filesystem location of an extension.
+location = Location
+
 # LOCALIZATION NOTE (workers):
 # This string is displayed as a header of the about:debugging#workers page.
 workers = Workers
 
 serviceWorkers = Service Workers
 sharedWorkers = Shared Workers
 otherWorkers = Other Workers
 
--- a/devtools/client/netmonitor/src/components/request-list-column-file.js
+++ b/devtools/client/netmonitor/src/components/request-list-column-file.js
@@ -35,17 +35,16 @@ const RequestListColumnFile = createClas
     return (
       div({
         className: "requests-list-column requests-list-file",
         title: urlDetails.unicodeUrl,
       },
         img({
           className: "requests-list-icon",
           src: responseContentDataUri,
-          "data-type": responseContentDataUri ? "thumbnail" : undefined,
         }),
         urlDetails.baseNameWithQuery
       )
     );
   }
 });
 
 module.exports = RequestListColumnFile;
--- a/devtools/client/netmonitor/src/constants.js
+++ b/devtools/client/netmonitor/src/constants.js
@@ -88,28 +88,16 @@ const EVENTS = {
   UPDATING_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdating:EventTimings",
   RECEIVED_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdated:EventTimings",
 
   // When response content begins, updates and finishes receiving.
   STARTED_RECEIVING_RESPONSE: "NetMonitor:NetworkEventUpdating:ResponseStart",
   UPDATING_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdating:ResponseContent",
   RECEIVED_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdated:ResponseContent",
 
-  // When the request post params are displayed in the UI.
-  REQUEST_POST_PARAMS_DISPLAYED: "NetMonitor:RequestPostParamsAvailable",
-
-  // When the image response thumbnail is displayed in the UI.
-  RESPONSE_IMAGE_THUMBNAIL_DISPLAYED:
-    "NetMonitor:ResponseImageThumbnailAvailable",
-
-  // Fired when charts have been displayed in the PerformanceStatisticsView.
-  PLACEHOLDER_CHARTS_DISPLAYED: "NetMonitor:PlaceholderChartsDisplayed",
-  PRIMED_CACHE_CHART_DISPLAYED: "NetMonitor:PrimedChartsDisplayed",
-  EMPTY_CACHE_CHART_DISPLAYED: "NetMonitor:EmptyChartsDisplayed",
-
   // Fired once the NetMonitorController establishes a connection to the debug
   // target.
   CONNECTED: "connected",
 };
 
 const HEADERS = [
   {
     name: "status",
--- a/devtools/client/netmonitor/src/netmonitor-controller.js
+++ b/devtools/client/netmonitor/src/netmonitor-controller.js
@@ -2,20 +2,17 @@
  * 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 strict";
 
 const { TimelineFront } = require("devtools/shared/fronts/timeline");
 const { CurlUtils } = require("devtools/client/shared/curl");
 const { ACTIVITY_TYPE, EVENTS } = require("./constants");
-const {
-  getRequestById,
-  getDisplayedRequestById,
-} = require("./selectors/index");
+const { getDisplayedRequestById } = require("./selectors/index");
 const {
   fetchHeaders,
   formDataURI,
 } = require("./utils/request-utils");
 const {
   getLongString,
   getWebConsoleClient,
   onFirefoxConnect,
@@ -302,17 +299,16 @@ function NetworkEventsHandler() {
   this._onNetworkEvent = this._onNetworkEvent.bind(this);
   this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
   this._onDocLoadingMarker = this._onDocLoadingMarker.bind(this);
   this._onRequestHeaders = this._onRequestHeaders.bind(this);
   this._onRequestCookies = this._onRequestCookies.bind(this);
   this._onRequestPostData = this._onRequestPostData.bind(this);
   this._onResponseHeaders = this._onResponseHeaders.bind(this);
   this._onResponseCookies = this._onResponseCookies.bind(this);
-  this._onResponseContent = this._onResponseContent.bind(this);
   this._onSecurityInfo = this._onSecurityInfo.bind(this);
   this._onEventTimings = this._onEventTimings.bind(this);
 }
 
 NetworkEventsHandler.prototype = {
   get client() {
     return NetMonitorController._target.client;
   },
@@ -423,125 +419,151 @@ NetworkEventsHandler.prototype = {
         fromCache,
         fromServiceWorker,
       },
       true
     )
     .then(() => window.emit(EVENTS.REQUEST_ADDED, id));
   },
 
-  async updateRequest(id, data) {
-    await this.actions.updateRequest(id, data, true);
-    let {
-      responseContent,
-      responseCookies,
-      responseHeaders,
-      requestCookies,
-      requestHeaders,
-      requestPostData,
-    } = data;
-    let request = getRequestById(window.gStore.getState(), id);
-
-    if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
-      let headers = await fetchHeaders(requestHeaders, getLongString);
-      if (headers) {
-        await this.actions.updateRequest(
-          id,
-          { requestHeaders: headers },
-          true,
-        );
-      }
-    }
-
-    if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
-      let headers = await fetchHeaders(responseHeaders, getLongString);
-      if (headers) {
-        await this.actions.updateRequest(
-          id,
-          { responseHeaders: headers },
-          true,
-        );
-      }
-    }
-
-    if (request && responseContent && responseContent.content) {
-      let { mimeType } = request;
-      let { text, encoding } = responseContent.content;
+  async fetchImage(mimeType, responseContent) {
+    let payload = {};
+    if (mimeType && responseContent && responseContent.content) {
+      let { encoding, text } = responseContent.content;
       let response = await getLongString(text);
-      let payload = {};
 
       if (mimeType.includes("image/")) {
         payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
       }
 
       responseContent.content.text = response;
       payload.responseContent = responseContent;
-
-      await this.actions.updateRequest(id, payload, true);
+    }
+    return payload;
+  },
 
-      if (mimeType.includes("image/")) {
-        window.emit(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
+  async fetchRequestHeaders(requestHeaders) {
+    let payload = {};
+    if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
+      let headers = await fetchHeaders(requestHeaders, getLongString);
+      if (headers) {
+        payload.requestHeaders = headers;
       }
     }
+    return payload;
+  },
 
-    // Search the POST data upload stream for request headers and add
-    // them as a separate property, different from the classic headers.
+  async fetchResponseHeaders(responseHeaders) {
+    let payload = {};
+    if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
+      let headers = await fetchHeaders(responseHeaders, getLongString);
+      if (headers) {
+        payload.responseHeaders = headers;
+      }
+    }
+    return payload;
+  },
+
+  // Search the POST data upload stream for request headers and add
+  // them as a separate property, different from the classic headers.
+  async fetchPostData(requestPostData) {
+    let payload = {};
     if (requestPostData && requestPostData.postData) {
       let { text } = requestPostData.postData;
       let postData = await getLongString(text);
       const headers = CurlUtils.getHeadersFromMultipartText(postData);
       const headersSize = headers.reduce((acc, { name, value }) => {
         return acc + name.length + value.length + 2;
       }, 0);
-      let payload = {};
       requestPostData.postData.text = postData;
       payload.requestPostData = Object.assign({}, requestPostData);
       payload.requestHeadersFromUploadStream = { headers, headersSize };
-
-      await this.actions.updateRequest(id, payload, true);
     }
+    return payload;
+  },
 
-    // Fetch request and response cookies long value.
-    // Actor does not provide full sized cookie value when the value is too long
-    // To display values correctly, we need fetch them in each request.
+  async fetchResponseCookies(responseCookies) {
+    let payload = {};
+    if (responseCookies) {
+      let resCookies = [];
+      // response store cookies in responseCookies or responseCookies.cookies
+      let cookies = responseCookies.cookies ?
+        responseCookies.cookies : responseCookies;
+      // make sure cookies is iterable
+      if (typeof cookies[Symbol.iterator] === "function") {
+        for (let cookie of cookies) {
+          resCookies.push(Object.assign({}, cookie, {
+            value: await getLongString(cookie.value),
+          }));
+        }
+        if (resCookies.length) {
+          payload.responseCookies = resCookies;
+        }
+      }
+    }
+    return payload;
+  },
+
+  // Fetch request and response cookies long value.
+  // Actor does not provide full sized cookie value when the value is too long
+  // To display values correctly, we need fetch them in each request.
+  async fetchRequestCookies(requestCookies) {
+    let payload = {};
     if (requestCookies) {
       let reqCookies = [];
       // request store cookies in requestCookies or requestCookies.cookies
       let cookies = requestCookies.cookies ?
         requestCookies.cookies : requestCookies;
       // make sure cookies is iterable
       if (typeof cookies[Symbol.iterator] === "function") {
         for (let cookie of cookies) {
           reqCookies.push(Object.assign({}, cookie, {
             value: await getLongString(cookie.value),
           }));
         }
         if (reqCookies.length) {
-          await this.actions.updateRequest(id, { requestCookies: reqCookies }, true);
+          payload.requestCookies = reqCookies;
         }
       }
     }
+    return payload;
+  },
 
-    if (responseCookies) {
-      let resCookies = [];
-      // response store cookies in responseCookies or responseCookies.cookies
-      let cookies = responseCookies.cookies ?
-        responseCookies.cookies : responseCookies;
-      // make sure cookies is iterable
-      if (typeof cookies[Symbol.iterator] === "function") {
-        for (let cookie of cookies) {
-          resCookies.push(Object.assign({}, cookie, {
-            value: await getLongString(cookie.value),
-          }));
-        }
-        if (resCookies.length) {
-          await this.actions.updateRequest(id, { responseCookies: resCookies }, true);
-        }
-      }
-    }
+  async updateRequest(id, data) {
+    let {
+      mimeType,
+      responseContent,
+      responseCookies,
+      responseHeaders,
+      requestCookies,
+      requestHeaders,
+      requestPostData,
+    } = data;
+
+    // fetch request detail contents in parallel
+    let [
+      imageObj,
+      requestHeadersObj,
+      responseHeadersObj,
+      postDataObj,
+      requestCookiesObj,
+      responseCookiesObj,
+    ] = await Promise.all([
+      this.fetchImage(mimeType, responseContent),
+      this.fetchRequestHeaders(requestHeaders),
+      this.fetchResponseHeaders(responseHeaders),
+      this.fetchPostData(requestPostData),
+      this.fetchRequestCookies(requestCookies),
+      this.fetchResponseCookies(responseCookies),
+    ]);
+
+    let payload = Object.assign({}, data,
+                                    imageObj, requestHeadersObj, responseHeadersObj,
+                                    postDataObj, requestCookiesObj, responseCookiesObj);
+    await this.actions.updateRequest(id, payload, true);
   },
 
   /**
    * The "networkEventUpdate" message type handler.
    *
    * @param string type
    *        Message type.
    * @param object packet
@@ -563,19 +585,20 @@ NetworkEventsHandler.prototype = {
       case "requestPostData":
         this.webConsoleClient.getRequestPostData(actor,
           this._onRequestPostData);
         window.emit(EVENTS.UPDATING_REQUEST_POST_DATA, actor);
         break;
       case "securityInfo":
         this.updateRequest(actor, {
           securityState: networkInfo.securityInfo,
+        }).then(() => {
+          this.webConsoleClient.getSecurityInfo(actor, this._onSecurityInfo);
+          window.emit(EVENTS.UPDATING_SECURITY_INFO, actor);
         });
-        this.webConsoleClient.getSecurityInfo(actor, this._onSecurityInfo);
-        window.emit(EVENTS.UPDATING_SECURITY_INFO, actor);
         break;
       case "responseHeaders":
         this.webConsoleClient.getResponseHeaders(actor,
           this._onResponseHeaders);
         window.emit(EVENTS.UPDATING_RESPONSE_HEADERS, actor);
         break;
       case "responseCookies":
         this.webConsoleClient.getResponseCookies(actor,
@@ -585,35 +608,36 @@ NetworkEventsHandler.prototype = {
       case "responseStart":
         this.updateRequest(actor, {
           httpVersion: networkInfo.response.httpVersion,
           remoteAddress: networkInfo.response.remoteAddress,
           remotePort: networkInfo.response.remotePort,
           status: networkInfo.response.status,
           statusText: networkInfo.response.statusText,
           headersSize: networkInfo.response.headersSize
+        }).then(() => {
+          window.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
         });
-        window.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
         break;
       case "responseContent":
-        this.updateRequest(actor, {
-          contentSize: networkInfo.response.bodySize,
-          transferredSize: networkInfo.response.transferredSize,
-          mimeType: networkInfo.response.content.mimeType
-        });
         this.webConsoleClient.getResponseContent(actor,
-          this._onResponseContent);
+          this._onResponseContent.bind(this, {
+            contentSize: networkInfo.response.bodySize,
+            transferredSize: networkInfo.response.transferredSize,
+            mimeType: networkInfo.response.content.mimeType
+          }));
         window.emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
         break;
       case "eventTimings":
         this.updateRequest(actor, {
           totalTime: networkInfo.totalTime
+        }).then(() => {
+          this.webConsoleClient.getEventTimings(actor, this._onEventTimings);
+          window.emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
         });
-        this.webConsoleClient.getEventTimings(actor, this._onEventTimings);
-        window.emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
         break;
     }
   },
 
   /**
    * Handles additional information received for a "requestHeaders" packet.
    *
    * @param object response
@@ -695,23 +719,24 @@ NetworkEventsHandler.prototype = {
     }).then(() => {
       window.emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
     });
   },
 
   /**
    * Handles additional information received for a "responseContent" packet.
    *
+   * @param object data
+   *        The message received from the server event.
    * @param object response
    *        The message received from the server.
    */
-  _onResponseContent: function (response) {
-    this.updateRequest(response.from, {
-      responseContent: response
-    }).then(() => {
+  _onResponseContent: function (data, response) {
+    let payload = Object.assign({ responseContent: response }, data);
+    this.updateRequest(response.from, payload).then(() => {
       window.emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
     });
   },
 
   /**
    * Handles additional information received for a "eventTimings" packet.
    *
    * @param object response
--- a/devtools/client/netmonitor/test/browser_net_icon-preview.js
+++ b/devtools/client/netmonitor/test/browser_net_icon-preview.js
@@ -4,74 +4,66 @@
 "use strict";
 
 /**
  * Tests if image responses show a thumbnail in the requests menu.
  */
 
 add_task(function* () {
   let { tab, monitor } = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
+  const SELECTOR = ".requests-list-icon[src]";
   info("Starting test... ");
 
   let { document, gStore, windowRequire } = monitor.panelWin;
   let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
   let { NetMonitorController } =
     windowRequire("devtools/client/netmonitor/src/netmonitor-controller");
-  let {
-    ACTIVITY_TYPE,
-    EVENTS,
-  } = windowRequire("devtools/client/netmonitor/src/constants");
+  let { ACTIVITY_TYPE } = windowRequire("devtools/client/netmonitor/src/constants");
 
   gStore.dispatch(Actions.batchEnable(false));
 
-  let wait = waitForEvents();
+  let wait = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
   yield performRequests();
   yield wait;
+  yield waitUntil(() => !!document.querySelector(SELECTOR));
 
   info("Checking the image thumbnail when all items are shown.");
   checkImageThumbnail();
 
   gStore.dispatch(Actions.sortBy("contentSize"));
   info("Checking the image thumbnail when all items are sorted.");
   checkImageThumbnail();
 
   gStore.dispatch(Actions.toggleRequestFilterType("images"));
   info("Checking the image thumbnail when only images are shown.");
   checkImageThumbnail();
 
   info("Reloading the debuggee and performing all requests again...");
-  wait = waitForEvents();
+  wait = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
   yield reloadAndPerformRequests();
   yield wait;
+  yield waitUntil(() => !!document.querySelector(SELECTOR));
 
   info("Checking the image thumbnail after a reload.");
   checkImageThumbnail();
 
   yield teardown(monitor);
 
-  function waitForEvents() {
-    return promise.all([
-      waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS),
-      monitor.panelWin.once(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED)
-    ]);
-  }
-
   function performRequests() {
     return ContentTask.spawn(tab.linkedBrowser, {}, function* () {
       content.wrappedJSObject.performRequests();
     });
   }
 
   function* reloadAndPerformRequests() {
     yield NetMonitorController.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
     yield performRequests();
   }
 
   function checkImageThumbnail() {
-    is(document.querySelectorAll(".requests-list-icon[data-type=thumbnail]").length, 1,
+    is(document.querySelectorAll(SELECTOR).length, 1,
       "There should be only one image request with a thumbnail displayed.");
-    is(document.querySelector(".requests-list-icon[data-type=thumbnail]").src,
-      TEST_IMAGE_DATA_URI,
+    is(document.querySelector(SELECTOR).src, TEST_IMAGE_DATA_URI,
       "The image requests-list-icon thumbnail is displayed correctly.");
-    is(document.querySelector(".requests-list-icon[data-type=thumbnail]").hidden, false,
+    is(document.querySelector(SELECTOR).hidden, false,
       "The image requests-list-icon thumbnail should not be hidden.");
   }
 });
--- a/devtools/client/netmonitor/test/browser_net_image-tooltip.js
+++ b/devtools/client/netmonitor/test/browser_net_image-tooltip.js
@@ -6,53 +6,49 @@
 const IMAGE_TOOLTIP_URL = EXAMPLE_URL + "html_image-tooltip-test-page.html";
 const IMAGE_TOOLTIP_REQUESTS = 1;
 
 /**
  * Tests if image responses show a popup in the requests menu when hovered.
  */
 add_task(function* test() {
   let { tab, monitor } = yield initNetMonitor(IMAGE_TOOLTIP_URL);
+  const SELECTOR = ".requests-list-icon[src]";
   info("Starting test... ");
 
   let { document, gStore, windowRequire } = monitor.panelWin;
   let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
   let { NetMonitorController } =
     windowRequire("devtools/client/netmonitor/src/netmonitor-controller");
-  let {
-    ACTIVITY_TYPE,
-    EVENTS,
-  } = windowRequire("devtools/client/netmonitor/src/constants");
+  let { ACTIVITY_TYPE } = windowRequire("devtools/client/netmonitor/src/constants");
   let toolboxDoc = monitor.panelWin.parent.document;
 
   gStore.dispatch(Actions.batchEnable(false));
 
   let onEvents = waitForNetworkEvents(monitor, IMAGE_TOOLTIP_REQUESTS);
-  let onThumbnail = monitor.panelWin.once(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
   yield performRequests();
   yield onEvents;
-  yield onThumbnail;
+  yield waitUntil(() => !!document.querySelector(SELECTOR));
 
   info("Checking the image thumbnail after a few requests were made...");
   yield showTooltipAndVerify(document.querySelectorAll(".request-list-item")[0]);
 
   // Hide tooltip before next test, to avoid the situation that tooltip covers
   // the icon for the request of the next test.
   info("Checking the image thumbnail gets hidden...");
   yield hideTooltipAndVerify(document.querySelectorAll(".request-list-item")[0]);
 
   // +1 extra document reload
   onEvents = waitForNetworkEvents(monitor, IMAGE_TOOLTIP_REQUESTS + 1);
-  onThumbnail = monitor.panelWin.once(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
 
   info("Reloading the debuggee and performing all requests again...");
   yield NetMonitorController.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
   yield performRequests();
   yield onEvents;
-  yield onThumbnail;
+  yield waitUntil(() => !!document.querySelector(SELECTOR));
 
   info("Checking the image thumbnail after a reload.");
   yield showTooltipAndVerify(document.querySelectorAll(".request-list-item")[1]);
 
   info("Checking if the image thumbnail is hidden when mouse leaves the menu widget");
   let requestsListContents = document.querySelector(".requests-list-contents");
   EventUtils.synthesizeMouse(requestsListContents, 0, 0, { type: "mouseout" },
                              monitor.panelWin);
--- a/devtools/client/netmonitor/test/browser_net_simple-request-data.js
+++ b/devtools/client/netmonitor/test/browser_net_simple-request-data.js
@@ -188,44 +188,26 @@ function test() {
         SIMPLE_SJS,
         {
           status: "200",
           statusText: "Och Aye"
         }
       );
     });
 
-    monitor.panelWin.once(EVENTS.UPDATING_RESPONSE_CONTENT, () => {
+    monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT, () => {
       let requestItem = getSortedRequests(gStore.getState()).get(0);
 
       is(requestItem.transferredSize, "12",
         "The transferredSize data has an incorrect value.");
       is(requestItem.contentSize, "12",
         "The contentSize data has an incorrect value.");
       is(requestItem.mimeType, "text/plain; charset=utf-8",
         "The mimeType data has an incorrect value.");
 
-      verifyRequestItemTarget(
-        document,
-        getDisplayedRequests(gStore.getState()),
-        requestItem,
-        "GET",
-        SIMPLE_SJS,
-        {
-          type: "plain",
-          fullMimeType: "text/plain; charset=utf-8",
-          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 12),
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 12),
-        }
-      );
-    });
-
-    monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT, () => {
-      let requestItem = getSortedRequests(gStore.getState()).get(0);
-
       ok(requestItem.responseContent,
         "There should be a responseContent data available.");
       // eslint-disable-next-line mozilla/no-cpows-in-tests
       is(requestItem.responseContent.content.mimeType,
         "text/plain; charset=utf-8",
         "The responseContent data has an incorrect |content.mimeType| property.");
       // eslint-disable-next-line mozilla/no-cpows-in-tests
       is(requestItem.responseContent.content.text,
--- a/devtools/client/shared/components/notification-box.js
+++ b/devtools/client/shared/components/notification-box.js
@@ -24,17 +24,17 @@ const PriorityLevels = {
   PRIORITY_CRITICAL_LOW: 7,
   PRIORITY_CRITICAL_MEDIUM: 8,
   PRIORITY_CRITICAL_HIGH: 9,
   PRIORITY_CRITICAL_BLOCK: 10,
 };
 
 /**
  * This component represents Notification Box - HTML alternative for
- * <xul:notifictionbox> binding.
+ * <xul:notificationbox> binding.
  *
  * See also MDN for more info about <xul:notificationbox>:
  * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/notificationbox
  */
 var NotificationBox = createClass({
   displayName: "NotificationBox",
 
   propTypes: {
--- a/devtools/shared/acorn/tests/unit/test_import_acorn.js
+++ b/devtools/shared/acorn/tests/unit/test_import_acorn.js
@@ -1,18 +1,18 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Test that we can require acorn.
- */
-
-function run_test() {
-  const acorn = require("acorn/acorn");
-  const acorn_loose = require("acorn/acorn_loose");
-  const walk = require("acorn/util/walk");
-  do_check_true(isObject(acorn));
-  do_check_true(isObject(acorn_loose));
-  do_check_true(isObject(walk));
-  do_check_eq(typeof acorn.parse, "function");
-  do_check_eq(typeof acorn_loose.parse_dammit, "function");
-  do_check_eq(typeof walk.simple, "function");
-}
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that we can require acorn.
+ */
+
+function run_test() {
+  const acorn = require("acorn/acorn");
+  const acorn_loose = require("acorn/acorn_loose");
+  const walk = require("acorn/util/walk");
+  do_check_true(isObject(acorn));
+  do_check_true(isObject(acorn_loose));
+  do_check_true(isObject(walk));
+  do_check_eq(typeof acorn.parse, "function");
+  do_check_eq(typeof acorn_loose.parse_dammit, "function");
+  do_check_eq(typeof walk.simple, "function");
+}
--- a/devtools/shared/acorn/tests/unit/test_lenient_parser.js
+++ b/devtools/shared/acorn/tests/unit/test_lenient_parser.js
@@ -1,62 +1,62 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Test that acorn's lenient parser gives something usable.
- */
-
-const acorn_loose = require("acorn/acorn_loose");
-
-function run_test() {
-  let actualAST = acorn_loose.parse_dammit("let x = 10", {});
-
-  do_print("Actual AST:");
-  do_print(JSON.stringify(actualAST, null, 2));
-  do_print("Expected AST:");
-  do_print(JSON.stringify(expectedAST, null, 2));
-
-  checkEquivalentASTs(expectedAST, actualAST);
-}
-
-const expectedAST = {
-  "type": "Program",
-  "start": 0,
-  "end": 10,
-  "body": [
-    {
-      "type": "ExpressionStatement",
-      "start": 0,
-      "end": 3,
-      "expression": {
-        "type": "Identifier",
-        "start": 0,
-        "end": 3,
-        "name": "let"
-      }
-    },
-    {
-      "type": "ExpressionStatement",
-      "start": 4,
-      "end": 10,
-      "expression": {
-        "type": "AssignmentExpression",
-        "start": 4,
-        "end": 10,
-        "operator": "=",
-        "left": {
-          "type": "Identifier",
-          "start": 4,
-          "end": 5,
-          "name": "x"
-        },
-        "right": {
-          "type": "Literal",
-          "start": 8,
-          "end": 10,
-          "value": 10,
-          "raw": "10"
-        }
-      }
-    }
-  ]
-};
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that acorn's lenient parser gives something usable.
+ */
+
+const acorn_loose = require("acorn/acorn_loose");
+
+function run_test() {
+  let actualAST = acorn_loose.parse_dammit("let x = 10", {});
+
+  do_print("Actual AST:");
+  do_print(JSON.stringify(actualAST, null, 2));
+  do_print("Expected AST:");
+  do_print(JSON.stringify(expectedAST, null, 2));
+
+  checkEquivalentASTs(expectedAST, actualAST);
+}
+
+const expectedAST = {
+  "type": "Program",
+  "start": 0,
+  "end": 10,
+  "body": [
+    {
+      "type": "ExpressionStatement",
+      "start": 0,
+      "end": 3,
+      "expression": {
+        "type": "Identifier",
+        "start": 0,
+        "end": 3,
+        "name": "let"
+      }
+    },
+    {
+      "type": "ExpressionStatement",
+      "start": 4,
+      "end": 10,
+      "expression": {
+        "type": "AssignmentExpression",
+        "start": 4,
+        "end": 10,
+        "operator": "=",
+        "left": {
+          "type": "Identifier",
+          "start": 4,
+          "end": 5,
+          "name": "x"
+        },
+        "right": {
+          "type": "Literal",
+          "start": 8,
+          "end": 10,
+          "value": 10,
+          "raw": "10"
+        }
+      }
+    }
+  ]
+};
--- a/devtools/shared/acorn/tests/unit/test_same_ast.js
+++ b/devtools/shared/acorn/tests/unit/test_same_ast.js
@@ -1,37 +1,37 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Test that Reflect and acorn create the same AST for ES5.
- */
-
-const acorn = require("acorn/acorn");
-const { Reflect } = require("resource://gre/modules/reflect.jsm");
-
-const testCode = "" + function main () {
-  function makeAcc(n) {
-    return function () {
-      return ++n;
-    };
-  }
-
-  var acc = makeAcc(10);
-
-  for (var i = 0; i < 10; i++) {
-    acc();
-  }
-
-  console.log(acc());
-};
-
-function run_test() {
-  const reflectAST = Reflect.parse(testCode);
-  const acornAST = acorn.parse(testCode);
-
-  do_print("Reflect AST:");
-  do_print(JSON.stringify(reflectAST, null, 2));
-  do_print("acorn AST:");
-  do_print(JSON.stringify(acornAST, null, 2));
-
-  checkEquivalentASTs(reflectAST, acornAST);
-}
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that Reflect and acorn create the same AST for ES5.
+ */
+
+const acorn = require("acorn/acorn");
+const { Reflect } = require("resource://gre/modules/reflect.jsm");
+
+const testCode = "" + function main () {
+  function makeAcc(n) {
+    return function () {
+      return ++n;
+    };
+  }
+
+  var acc = makeAcc(10);
+
+  for (var i = 0; i < 10; i++) {
+    acc();
+  }
+
+  console.log(acc());
+};
+
+function run_test() {
+  const reflectAST = Reflect.parse(testCode);
+  const acornAST = acorn.parse(testCode);
+
+  do_print("Reflect AST:");
+  do_print(JSON.stringify(reflectAST, null, 2));
+  do_print("acorn AST:");
+  do_print(JSON.stringify(acornAST, null, 2));
+
+  checkEquivalentASTs(reflectAST, acornAST);
+}
--- a/dom/base/domerr.msg
+++ b/dom/base/domerr.msg
@@ -140,16 +140,17 @@ DOM4_MSG_DEF(QuotaExceededError, "The cu
 
 /* Push API errors. */
 DOM4_MSG_DEF(InvalidStateError, "Invalid service worker registration.", NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR)
 DOM4_MSG_DEF(NotAllowedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR)
 DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR)
 DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE)
 DOM4_MSG_DEF(InvalidAccessError, "Invalid raw ECDSA P-256 public key.", NS_ERROR_DOM_PUSH_INVALID_KEY_ERR)
 DOM4_MSG_DEF(InvalidStateError, "A subscription with a different application server key already exists.", NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR)
+DOM4_MSG_DEF(InvalidStateError, "GCM service disabled.", NS_ERROR_DOM_PUSH_GCM_DISABLED)
 
 /* Media errors */
 DOM4_MSG_DEF(AbortError,        "The fetching process for the media resource was aborted by the user agent at the user's request.", NS_ERROR_DOM_MEDIA_ABORT_ERR)
 DOM4_MSG_DEF(NotAllowedError,   "The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR)
 DOM4_MSG_DEF(NotSupportedError, "The media resource indicated by the src attribute or assigned media provider object was not suitable.", NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR)
 
 DOM4_MSG_DEF(SyntaxError, "The URI is malformed.", NS_ERROR_DOM_MALFORMED_URI)
 DOM4_MSG_DEF(SyntaxError, "Invalid header name.", NS_ERROR_DOM_INVALID_HEADER_NAME)
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -115,16 +115,18 @@ skip-if = toolkit == 'android'  # Bug 11
 [test_peerConnection_basicAudioVideoNoBundle.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicAudioVideoNoBundleNoRtcpMux.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicAudioVideoNoRtcpMux.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicVideo.html]
 skip-if = (android_version == '18' && debug) # android(Bug 1189784, timeouts on 4.3 emulator)
+[test_peerConnection_basicVideoRemoteHwEncoder.html]
+skip-if = os == 'linux' || os == 'mac' || os == 'win' || (android_version == '18' && debug) # android-specific feature. android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicScreenshare.html]
 # frequent timeouts/crashes on e10s (bug 1048455)
 skip-if = toolkit == 'android' # no screenshare on android
 [test_peerConnection_basicWindowshare.html]
 # frequent timeouts/crashes on e10s (bug 1048455)
 skip-if = toolkit == 'android' # no screenshare on android
 [test_peerConnection_basicH264Video.html]
 skip-if = toolkit == 'android' # Bug 1043403, Bug 1355786, Bug 1149374
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_basicVideoRemoteHwEncoder.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1265755",
+    title: "Basic video peer connection with android oop hw encoder"
+  });
+
+  runNetworkTest(options => {
+    SpecialPowers.pushPrefEnv(
+      {
+        set: [
+          ['media.navigator.hardware.vp8_encode.acceleration_enabled', true],
+          ['media.navigator.hardware.vp8_encode.acceleration_remote_enabled', true]
+        ]
+      }, function (options = {}) {
+        var test = new PeerConnectionTest(options);
+        test.setMediaConstraints([{video: true}],
+                                 [{video: true}]);
+        test.run();
+      })
+  });
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -21,20 +21,18 @@
 #include "nsCRTGlue.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
-#include "nsIDOMNodeIterator.h"
 #include "nsIDOMText.h"
 #include "nsNameSpaceManager.h"
 #include "nsINode.h"
 #include "nsIPlaintextEditor.h"
 #include "nsISupportsBase.h"
 #include "nsLiteralString.h"
 #include "nsUnicharUtils.h"
 #include "nsIHTMLCollection.h"
@@ -186,17 +184,17 @@ TextEditRules::BeforeEdit(EditAction act
   }
   mActionNesting++;
 
   // get the selection and cache the position before editing
   NS_ENSURE_STATE(mTextEditor);
   RefPtr<Selection> selection = mTextEditor->GetSelection();
   NS_ENSURE_STATE(selection);
 
-  selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode));
+  mCachedSelectionNode = selection->GetAnchorNode();
   selection->GetAnchorOffset(&mCachedSelectionOffset);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextEditRules::AfterEdit(EditAction action,
                          nsIEditor::EDirection aDirection)
@@ -211,17 +209,17 @@ TextEditRules::AfterEdit(EditAction acti
   if (!--mActionNesting) {
     NS_ENSURE_STATE(mTextEditor);
     RefPtr<Selection> selection = mTextEditor->GetSelection();
     NS_ENSURE_STATE(selection);
 
     NS_ENSURE_STATE(mTextEditor);
     nsresult rv =
       mTextEditor->HandleInlineSpellCheck(action, selection,
-                                          mCachedSelectionNode,
+                                          GetAsDOMNode(mCachedSelectionNode),
                                           mCachedSelectionOffset,
                                           nullptr, 0, nullptr, 0);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // if only trailing <br> remaining remove it
     rv = RemoveRedundantTrailingBR();
     if (NS_FAILED(rv)) {
       return rv;
@@ -990,17 +988,17 @@ TextEditRules::DidUndo(Selection* aSelec
   // If aResult is an error, we return it.
   NS_ENSURE_SUCCESS(aResult, aResult);
 
   NS_ENSURE_STATE(mTextEditor);
   dom::Element* theRoot = mTextEditor->GetRoot();
   NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
   nsIContent* node = mTextEditor->GetLeftmostChild(theRoot);
   if (node && mTextEditor->IsMozEditorBogusNode(node)) {
-    mBogusNode = do_QueryInterface(node);
+    mBogusNode = node;
   } else {
     mBogusNode = nullptr;
   }
   return aResult;
 }
 
 nsresult
 TextEditRules::WillRedo(Selection* aSelection,
@@ -1040,17 +1038,17 @@ TextEditRules::DidRedo(Selection* aSelec
   if (len != 1) {
     // only in the case of one br could there be the bogus node
     mBogusNode = nullptr;
     return NS_OK;
   }
 
   RefPtr<Element> node = nodeList->Item(0);
   if (mTextEditor->IsMozEditorBogusNode(node)) {
-    mBogusNode = do_QueryInterface(node);
+    mBogusNode = node;
   } else {
     mBogusNode = nullptr;
   }
   return NS_OK;
 }
 
 nsresult
 TextEditRules::WillOutputText(Selection* aSelection,
@@ -1126,17 +1124,17 @@ TextEditRules::RemoveRedundantTrailingBR
     return NS_OK;
   }
 
   // Rather than deleting this node from the DOM tree we should instead
   // morph this br into the bogus node
   elem->UnsetAttr(kNameSpaceID_None, nsGkAtoms::type, true);
 
   // set mBogusNode to be this <br>
-  mBogusNode = do_QueryInterface(elem);
+  mBogusNode = elem;
 
   // give it the bogus node attribute
   elem->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
                 kMOZEditorBogusNodeValue, false);
   return NS_OK;
 }
 
 nsresult
@@ -1215,26 +1213,24 @@ TextEditRules::CreateBogusNodeIfNeeded(S
     return NS_OK;
   }
 
   // Create a br.
   nsCOMPtr<Element> newContent = mTextEditor->CreateHTMLContent(nsGkAtoms::br);
   NS_ENSURE_STATE(newContent);
 
   // set mBogusNode to be the newly created <br>
-  mBogusNode = do_QueryInterface(newContent);
-  NS_ENSURE_TRUE(mBogusNode, NS_ERROR_NULL_POINTER);
+  mBogusNode = newContent;
 
   // Give it a special attribute.
   newContent->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
                       kMOZEditorBogusNodeValue, false);
 
   // Put the node in the document.
-  nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(body);
-  nsresult rv = mTextEditor->InsertNode(mBogusNode, bodyNode, 0);
+  nsresult rv = mTextEditor->InsertNode(*mBogusNode, *body, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set selection.
   aSelection->CollapseNative(body, 0);
   return NS_OK;
 }
 
 
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -11,17 +11,16 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIEditRules.h"
 #include "nsIEditor.h"
 #include "nsISupportsImpl.h"
 #include "nsITimer.h"
 #include "nsString.h"
 #include "nscore.h"
 
-class nsIDOMElement;
 class nsIDOMNode;
 
 namespace mozilla {
 
 class AutoLockRulesSniffing;
 class TextEditor;
 namespace dom {
 class Selection;
@@ -119,17 +118,16 @@ protected:
   nsresult WillInsertText(EditAction aAction,
                           Selection* aSelection,
                           bool* aCancel,
                           bool* aHandled,
                           const nsAString* inString,
                           nsAString* outString,
                           int32_t aMaxLength);
   nsresult DidInsertText(Selection* aSelection, nsresult aResult);
-  nsresult GetTopEnclosingPre(nsIDOMNode* aNode, nsIDOMNode** aOutPreNode);
 
   nsresult WillInsertBreak(Selection* aSelection, bool* aCancel,
                            bool* aHandled, int32_t aMaxLength);
   nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
 
   void WillInsert(Selection& aSelection, bool* aCancel);
   nsresult DidInsert(Selection* aSelection, nsresult aResult);
 
@@ -230,19 +228,19 @@ private:
 
 protected:
   // A buffer we use to store the real value of password editors.
   nsString mPasswordText;
   // A buffer we use to track the IME composition string.
   nsString mPasswordIMEText;
   uint32_t mPasswordIMEIndex;
   // Magic node acts as placeholder in empty doc.
-  nsCOMPtr<nsIDOMNode> mBogusNode;
+  nsCOMPtr<nsIContent> mBogusNode;
   // Cached selected node.
-  nsCOMPtr<nsIDOMNode> mCachedSelectionNode;
+  nsCOMPtr<nsINode> mCachedSelectionNode;
   // Cached selected offset.
   int32_t mCachedSelectionOffset;
   uint32_t mActionNesting;
   bool mLockRulesSniffing;
   bool mDidExplicitlySetInterline;
   // In bidirectional text, delete characters not visually adjacent to the
   // caret without moving the caret first.
   bool mDeleteBidiImmediately;
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -1293,26 +1293,28 @@ struct ParamTraits<mozilla::layers::Asyn
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mViewId);
     WriteParam(aMsg, aParam.mPresShellId);
     WriteParam(aMsg, aParam.mDragStartSequenceNumber);
     WriteParam(aMsg, aParam.mScrollbarDragOffset);
     WriteParam(aMsg, aParam.mScrollTrack);
+    WriteParam(aMsg, aParam.mScrollThumbLength);
     WriteParam(aMsg, aParam.mDirection);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mViewId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mDragStartSequenceNumber) &&
             ReadParam(aMsg, aIter, &aResult->mScrollbarDragOffset) &&
             ReadParam(aMsg, aIter, &aResult->mScrollTrack) &&
+            ReadParam(aMsg, aIter, &aResult->mScrollThumbLength) &&
             ReadParam(aMsg, aIter, &aResult->mDirection));
   }
 };
 
 template <>
 struct ParamTraits<mozilla::gfx::Glyph>
 {
   typedef mozilla::gfx::Glyph paramType;
--- a/gfx/layers/LayerMetricsWrapper.h
+++ b/gfx/layers/LayerMetricsWrapper.h
@@ -406,25 +406,16 @@ public:
 
   FrameMetrics::ViewID GetScrollbarTargetContainerId() const
   {
     MOZ_ASSERT(IsValid());
 
     return mLayer->GetScrollbarTargetContainerId();
   }
 
-  int32_t GetScrollThumbLength() const
-  {
-    if (GetScrollbarDirection() == ScrollDirection::VERTICAL) {
-      return mLayer->GetVisibleRegion().GetBounds().height;
-    } else {
-      return mLayer->GetVisibleRegion().GetBounds().width;
-    }
-  }
-
   bool IsScrollbarContainer() const
   {
     MOZ_ASSERT(IsValid());
     return mLayer->IsScrollbarContainer();
   }
 
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
   {
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -490,17 +490,16 @@ APZCTreeManager::PrepareNodeForLayer(con
     AttachNodeToTree(node, aParent, aNextSibling);
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetTransformTyped(),
         aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(),
         GetEventRegionsOverride(aParent, aLayer));
     node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
                            aLayer.GetScrollbarDirection(),
-                           aLayer.GetScrollThumbLength(),
                            aLayer.IsScrollbarContainer());
     node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
     return node;
   }
 
   AsyncPanZoomController* apzc = nullptr;
   // If we get here, aLayer is a scrollable layer and somebody
   // has registered a GeckoContentController for it, so we need to ensure
@@ -680,17 +679,16 @@ APZCTreeManager::PrepareNodeForLayer(con
         GetEventRegionsOverride(aParent, aLayer));
   }
 
   // Note: if layer properties must be propagated to nodes, RecvUpdate in
   // LayerTransactionParent.cpp must ensure that APZ will be notified
   // when those properties change.
   node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
                          aLayer.GetScrollbarDirection(),
-                         aLayer.GetScrollThumbLength(),
                          aLayer.IsScrollbarContainer());
   node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
   return node;
 }
 
 template<typename PanGestureOrScrollWheelInput>
 static bool
 WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput)
--- a/gfx/layers/apz/src/AsyncDragMetrics.h
+++ b/gfx/layers/apz/src/AsyncDragMetrics.h
@@ -29,37 +29,41 @@ public:
   };
 
   // IPC constructor
   AsyncDragMetrics()
     : mViewId(0)
     , mPresShellId(0)
     , mDragStartSequenceNumber(0)
     , mScrollbarDragOffset(0)
+    , mScrollThumbLength(0)
     , mDirection(NONE)
   {}
 
   AsyncDragMetrics(const FrameMetrics::ViewID& aViewId,
                    uint32_t aPresShellId,
                    uint64_t aDragStartSequenceNumber,
                    CSSCoord aScrollbarDragOffset,
                    const CSSRect& aScrollTrack,
+                   CSSCoord aScrollThumbLength,
                    DragDirection aDirection)
     : mViewId(aViewId)
     , mPresShellId(aPresShellId)
     , mDragStartSequenceNumber(aDragStartSequenceNumber)
     , mScrollbarDragOffset(aScrollbarDragOffset)
     , mScrollTrack(aScrollTrack)
+    , mScrollThumbLength(aScrollThumbLength)
     , mDirection(aDirection)
   {}
 
   FrameMetrics::ViewID mViewId;
   uint32_t mPresShellId;
   uint64_t mDragStartSequenceNumber;
   CSSCoord mScrollbarDragOffset;
   CSSRect mScrollTrack;
+  CSSCoord mScrollThumbLength;
   DragDirection mDirection;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -922,19 +922,17 @@ nsEventStatus AsyncPanZoomController::Ha
   CSSRect cssCompositionBound = mFrameMetrics.CalculateCompositedRectInCssPixels();
 
   CSSCoord mousePosition = GetAxisStart(aDragMetrics.mDirection, scrollbarPoint) -
                         aDragMetrics.mScrollbarDragOffset -
                         GetAxisStart(aDragMetrics.mDirection, cssCompositionBound) -
                         GetAxisStart(aDragMetrics.mDirection, aDragMetrics.mScrollTrack);
 
   CSSCoord scrollMax = GetAxisLength(aDragMetrics.mDirection, aDragMetrics.mScrollTrack);
-  scrollMax -= node->GetScrollThumbLength() /
-               GetAxisScale(aDragMetrics.mDirection, mFrameMetrics.GetZoom()) *
-               mFrameMetrics.GetPresShellResolution();
+  scrollMax -= aDragMetrics.mScrollThumbLength;
 
   float scrollPercent = mousePosition / scrollMax;
 
   CSSCoord minScrollPosition =
     GetAxisStart(aDragMetrics.mDirection, mFrameMetrics.GetScrollableRect().TopLeft());
   CSSCoord maxScrollPosition =
     GetAxisLength(aDragMetrics.mDirection, mFrameMetrics.GetScrollableRect()) -
     GetAxisLength(aDragMetrics.mDirection, cssCompositionBound);
--- a/gfx/layers/apz/src/HitTestingTreeNode.cpp
+++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp
@@ -23,17 +23,16 @@ namespace layers {
 HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc,
                                        bool aIsPrimaryHolder,
                                        uint64_t aLayersId)
   : mApzc(aApzc)
   , mIsPrimaryApzcHolder(aIsPrimaryHolder)
   , mLayersId(aLayersId)
   , mScrollViewId(FrameMetrics::NULL_SCROLL_ID)
   , mScrollDir(ScrollDirection::NONE)
-  , mScrollThumbLength(0)
   , mIsScrollbarContainer(false)
   , mFixedPosTarget(FrameMetrics::NULL_SCROLL_ID)
   , mOverride(EventRegionsOverride::NoOverride)
 {
 if (mIsPrimaryApzcHolder) {
     MOZ_ASSERT(mApzc);
   }
   MOZ_ASSERT(!mApzc || mApzc->GetLayersId() == mLayersId);
@@ -92,41 +91,33 @@ HitTestingTreeNode::SetLastChild(HitTest
       aChild->SetApzcParent(parent);
     }
   }
 }
 
 void
 HitTestingTreeNode::SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
                                      ScrollDirection aDir,
-                                     int32_t aScrollThumbLength,
                                      bool aIsScrollContainer)
 {
   mScrollViewId = aScrollViewId;
   mScrollDir = aDir;
-  mScrollThumbLength = aScrollThumbLength;
   mIsScrollbarContainer = aIsScrollContainer;
 }
 
 bool
 HitTestingTreeNode::MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const
 {
   return ((mScrollDir == ScrollDirection::HORIZONTAL &&
            aDragMetrics.mDirection == AsyncDragMetrics::HORIZONTAL) ||
           (mScrollDir == ScrollDirection::VERTICAL &&
            aDragMetrics.mDirection == AsyncDragMetrics::VERTICAL)) &&
          mScrollViewId == aDragMetrics.mViewId;
 }
 
-LayerIntCoord
-HitTestingTreeNode::GetScrollThumbLength() const
-{
-  return mScrollThumbLength;
-}
-
 bool
 HitTestingTreeNode::IsScrollbarNode() const
 {
   return mIsScrollbarContainer || (mScrollDir != ScrollDirection::NONE);
 }
 
 FrameMetrics::ViewID
 HitTestingTreeNode::GetScrollTargetId() const
--- a/gfx/layers/apz/src/HitTestingTreeNode.h
+++ b/gfx/layers/apz/src/HitTestingTreeNode.h
@@ -88,17 +88,16 @@ public:
                       const Maybe<ParentLayerIntRegion>& aClipRegion,
                       const EventRegionsOverride& aOverride);
   bool IsOutsideClip(const ParentLayerPoint& aPoint) const;
 
   /* Scrollbar info */
 
   void SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
                         ScrollDirection aDir,
-                        int32_t aScrollThumbLength,
                         bool aIsScrollContainer);
   bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
   LayerIntCoord GetScrollThumbLength() const;
   bool IsScrollbarNode() const;
   FrameMetrics::ViewID GetScrollTargetId() const;
 
   /* Fixed pos info */
 
@@ -130,17 +129,16 @@ private:
   uint64_t mLayersId;
 
   // This is set for both scroll track and scroll thumb Container layers, and
   // represents the scroll id of the scroll frame scrolled by the scrollbar.
   FrameMetrics::ViewID mScrollViewId;
 
   // This is set for scroll thumb Container layers only.
   ScrollDirection mScrollDir;
-  int32_t mScrollThumbLength;
 
   // This is set for scroll track Container layers only.
   bool mIsScrollbarContainer;
 
   FrameMetrics::ViewID mFixedPosTarget;
 
   /* Let {L,M} be the {layer, scrollable metrics} pair that this node
    * corresponds to in the layer tree. mEventRegions contains the event regions
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -712,17 +712,17 @@ MessageChannel::Clear()
     }
 
     if (mWorkerLoop) {
         mWorkerLoop->RemoveDestructionObserver(this);
     }
 
     gUnresolvedPromises -= mPendingPromises.size();
     for (auto& pair : mPendingPromises) {
-        pair.second.mRejectFunction(__func__);
+        pair.second.mRejectFunction(pair.second.mPromise, __func__);
     }
     mPendingPromises.clear();
 
     mWorkerLoop = nullptr;
     delete mLink;
     mLink = nullptr;
 
     mOnChannelConnectedTask->Cancel();
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -93,17 +93,17 @@ class MessageChannel : HasResultCodes, M
     class CxxStackFrame;
     class InterruptFrame;
 
     typedef mozilla::Monitor Monitor;
 
     struct PromiseHolder
     {
         RefPtr<MozPromiseRefcountable> mPromise;
-        std::function<void(const char*)> mRejectFunction;
+        std::function<void(MozPromiseRefcountable*, const char*)> mRejectFunction;
     };
     static Atomic<size_t> gUnresolvedPromises;
     friend class PromiseReporter;
 
   public:
     static const int32_t kNoTimeout;
 
     typedef IPC::Message Message;
@@ -181,18 +181,20 @@ class MessageChannel : HasResultCodes, M
     bool Send(Message* aMsg, Promise* aPromise) {
         int32_t seqno = NextSeqno();
         aMsg->set_seqno(seqno);
         if (!Send(aMsg)) {
             return false;
         }
         PromiseHolder holder;
         holder.mPromise = aPromise;
-        holder.mRejectFunction = [aPromise](const char* aRejectSite) {
-            aPromise->Reject(PromiseRejectReason::ChannelClosed, aRejectSite);
+        holder.mRejectFunction = [](MozPromiseRefcountable* aRejectPromise,
+                                    const char* aRejectSite) {
+            static_cast<Promise*>(aRejectPromise)->Reject(
+                PromiseRejectReason::ChannelClosed, aRejectSite);
         };
         mPendingPromises.insert(std::make_pair(seqno, Move(holder)));
         gUnresolvedPromises++;
         return true;
     }
 
     void SendBuildID();
 
--- a/ipc/ipdl/test/cxx/TestAsyncReturns.cpp
+++ b/ipc/ipdl/test/cxx/TestAsyncReturns.cpp
@@ -1,12 +1,14 @@
 #include "TestAsyncReturns.h"
 
 #include "IPDLUnitTests.h"      // fail etc.
 
+#include "mozilla/Unused.h"
+
 namespace mozilla {
 namespace _ipdltest {
 
 static uint32_t sMagic1 = 0x105b59fb;
 static uint32_t sMagic2 = 0x09b6f5e3;
 
 //-----------------------------------------------------------------------------
 // parent
@@ -74,17 +76,17 @@ TestAsyncReturnsChild::~TestAsyncReturns
 {
   MOZ_COUNT_DTOR(TestAsyncReturnsChild);
 }
 
 mozilla::ipc::IPCResult
 TestAsyncReturnsChild::RecvNoReturn(RefPtr<NoReturnPromise>&& aPromise)
 {
   // Leak the promise intentionally
-  aPromise->AddRef();
+  Unused << do_AddRef(aPromise);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TestAsyncReturnsChild::RecvPing(RefPtr<PingPromise>&& aPromise)
 {
   if (!AbstractThread::GetCurrent()) {
     fail("AbstractThread not initalized");
--- a/layout/reftests/forms/progress/reftest-stylo.list
+++ b/layout/reftests/forms/progress/reftest-stylo.list
@@ -1,34 +1,34 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-fails == values.html values.html
-fails == values-rtl.html values-rtl.html
-fails == margin-padding.html margin-padding.html
-fails == margin-padding-rtl.html margin-padding-rtl.html
+== values.html values.html
+== values-rtl.html values-rtl.html
+== margin-padding.html margin-padding.html
+== margin-padding-rtl.html margin-padding-rtl.html
 fails == bar-pseudo-element.html bar-pseudo-element.html
-fails == bar-pseudo-element-rtl.html bar-pseudo-element-rtl.html
-fails == indeterminate-style-width.html indeterminate-style-width.html
+== bar-pseudo-element-rtl.html bar-pseudo-element-rtl.html
+== indeterminate-style-width.html indeterminate-style-width.html
 
 # vertical tests
-fails == values-vertical.html values-vertical.html
-fails == values-vertical-rtl.html values-vertical-rtl.html
-fails == margin-padding-vertical.html margin-padding-vertical.html
-fails == margin-padding-vertical-rtl.html margin-padding-vertical-rtl.html
-fails == bar-pseudo-element-vertical.html bar-pseudo-element-vertical.html
-fails == bar-pseudo-element-vertical-rtl.html bar-pseudo-element-vertical-rtl.html
-fails == indeterminate-style-height.html indeterminate-style-height.html
+== values-vertical.html values-vertical.html
+== values-vertical-rtl.html values-vertical-rtl.html
+== margin-padding-vertical.html margin-padding-vertical.html
+== margin-padding-vertical-rtl.html margin-padding-vertical-rtl.html
+== bar-pseudo-element-vertical.html bar-pseudo-element-vertical.html
+== bar-pseudo-element-vertical-rtl.html bar-pseudo-element-vertical-rtl.html
+== indeterminate-style-height.html indeterminate-style-height.html
 
 # The following test is disabled but kept in the repository because the
 # transformations will not behave exactly the same for <progress> and two divs.
 # However, it would be possible to manually check those.
-fails == transformations.html transformations.html
+== transformations.html transformations.html
 
 # Tests for bugs:
-fails == block-invalidate.html block-invalidate.html
-fails == in-cells.html in-cells.html
+== block-invalidate.html block-invalidate.html
+== in-cells.html in-cells.html
 == max-height.html max-height.html
 
 # Tests for block and inline orientation in combination with writing-mode
 fails == progress-orient-horizontal.html progress-orient-horizontal.html
 fails-if(!cocoaWidget||OSX==1010) == progress-orient-vertical.html progress-orient-vertical.html
 fails == progress-orient-block.html progress-orient-block.html
 fails == progress-orient-inline.html progress-orient-inline.html
 fails == progress-vlr.html progress-vlr.html
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -452,51 +452,61 @@ Gecko_StyleAnimationsEquals(RawGeckoStyl
 }
 
 void
 Gecko_UpdateAnimations(RawGeckoElementBorrowed aElement,
                        nsIAtom* aPseudoTagOrNull,
                        ServoComputedValuesBorrowedOrNull aOldComputedValues,
                        ServoComputedValuesBorrowedOrNull aComputedValues,
                        ServoComputedValuesBorrowedOrNull aParentComputedValues,
-                       UpdateAnimationsTasks aTaskBits)
+                       UpdateAnimationsTasks aTasks)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aElement);
   MOZ_ASSERT(!aPseudoTagOrNull ||
              aPseudoTagOrNull == nsCSSPseudoElements::before ||
              aPseudoTagOrNull == nsCSSPseudoElements::after);
 
   nsPresContext* presContext = nsContentUtils::GetContextForContent(aElement);
   if (!presContext) {
     return;
   }
 
-  UpdateAnimationsTasks tasks = static_cast<UpdateAnimationsTasks>(aTaskBits);
   if (presContext->IsDynamic() && aElement->IsInComposedDoc()) {
     const ServoComputedValuesWithParent servoValues =
       { aComputedValues, aParentComputedValues };
     CSSPseudoElementType pseudoType =
       nsCSSPseudoElements::GetPseudoType(aPseudoTagOrNull,
                                          CSSEnabledState::eForAllContent);
 
-    if (tasks & UpdateAnimationsTasks::CSSAnimations) {
+    if (aTasks & UpdateAnimationsTasks::CSSAnimations) {
       presContext->AnimationManager()->
         UpdateAnimations(const_cast<dom::Element*>(aElement), pseudoType,
                          servoValues);
     }
-    if (tasks & UpdateAnimationsTasks::CSSTransitions) {
+
+    // aComputedValues might be nullptr if the target element is now in a
+    // display:none subtree. We still call Gecko_UpdateAnimations in this case
+    // because we need to stop CSS animations in the display:none subtree.
+    // However, we don't need to update transitions since they are stopped by
+    // RestyleManager::AnimationsWithDestroyedFrame so we just return early
+    // here.
+    if (!aComputedValues) {
+      return;
+    }
+
+    if (aTasks & UpdateAnimationsTasks::CSSTransitions) {
       MOZ_ASSERT(aOldComputedValues);
       const ServoComputedValuesWithParent oldServoValues =
         { aOldComputedValues, nullptr };
       presContext->TransitionManager()->
         UpdateTransitions(const_cast<dom::Element*>(aElement), pseudoType,
                           oldServoValues, servoValues);
     }
-    if (tasks & UpdateAnimationsTasks::EffectProperties) {
+    if (aTasks & UpdateAnimationsTasks::EffectProperties) {
       presContext->EffectCompositor()->UpdateEffectProperties(
         servoValues, const_cast<dom::Element*>(aElement), pseudoType);
     }
   }
 }
 
 bool
 Gecko_ElementHasAnimations(RawGeckoElementBorrowed aElement,
@@ -954,16 +964,43 @@ Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* 
   // XXXbholley: We should be able to do this without converting, I just can't
   // find the right thing to call.
   nsDependentAtomString atomStr(aAtom);
   NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
   return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr);
 }
 
 void
+Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder)
+{
+  aBorder->EnsureBorderColors();
+}
+
+void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide)
+{
+  aBorder->ClearBorderColors(aSide);
+}
+
+void
+Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide,
+                            nscolor aColor)
+{
+  aBorder->AppendBorderColor(aSide, aColor);
+}
+
+void
+Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
+                          mozilla::Side aSide)
+{
+  if (aSrc->mBorderColors) {
+    aDest->CopyBorderColorsFrom(aSrc->mBorderColors[aSide], aSide);
+  }
+}
+
+void
 Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
   aList->Clear();
 }
 
 void
 Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName, bool aQuoted)
 {
   FontFamilyName family;
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -31,16 +31,17 @@ class nsIAtom;
 class nsIPrincipal;
 class nsIURI;
 struct nsFont;
 namespace mozilla {
   class ServoStyleSheet;
   class FontFamilyList;
   enum FontFamilyType : uint32_t;
   struct Keyframe;
+  enum Side;
   namespace css {
     struct URLValue;
   };
   enum class UpdateAnimationsTasks : uint8_t;
   struct LangGroupFontPrefs;
 }
 using mozilla::FontFamilyList;
 using mozilla::FontFamilyType;
@@ -195,17 +196,17 @@ Gecko_GetAnimationRule(RawGeckoElementBo
                        RawServoAnimationValueMapBorrowed aAnimationValues);
 bool Gecko_StyleAnimationsEquals(RawGeckoStyleAnimationListBorrowed,
                                  RawGeckoStyleAnimationListBorrowed);
 void Gecko_UpdateAnimations(RawGeckoElementBorrowed aElement,
                             nsIAtom* aPseudoTagOrNull,
                             ServoComputedValuesBorrowedOrNull aOldComputedValues,
                             ServoComputedValuesBorrowedOrNull aComputedValues,
                             ServoComputedValuesBorrowedOrNull aParentComputedValues,
-                            mozilla::UpdateAnimationsTasks aTaskBits);
+                            mozilla::UpdateAnimationsTasks aTasks);
 bool Gecko_ElementHasAnimations(RawGeckoElementBorrowed aElement,
                                 nsIAtom* aPseudoTagOrNull);
 bool Gecko_ElementHasCSSAnimations(RawGeckoElementBorrowed aElement,
                                    nsIAtom* aPseudoTagOrNull);
 bool Gecko_ElementHasCSSTransitions(RawGeckoElementBorrowed aElement,
                                     nsIAtom* aPseudoTagOrNull);
 size_t Gecko_ElementTransitions_Length(RawGeckoElementBorrowed aElement,
                                        nsIAtom* aPseudoTagOrNull);
@@ -234,16 +235,24 @@ RawServoAnimationValueBorrowedOrNull Gec
 nsIAtom* Gecko_Atomize(const char* aString, uint32_t aLength);
 nsIAtom* Gecko_Atomize16(const nsAString* aString);
 void Gecko_AddRefAtom(nsIAtom* aAtom);
 void Gecko_ReleaseAtom(nsIAtom* aAtom);
 const uint16_t* Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength);
 bool Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength);
 bool Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength);
 
+// Border style
+void Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder);
+void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide);
+void Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide,
+                                 nscolor aColor);
+void Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
+                               mozilla::Side aSide);
+
 // Font style
 void Gecko_FontFamilyList_Clear(FontFamilyList* aList);
 void Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName, bool aQuoted);
 void Gecko_FontFamilyList_AppendGeneric(FontFamilyList* list, FontFamilyType familyType);
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
 // will not run destructors on dst, give it uninitialized memory
 // font_id is LookAndFeel::FontID
 void Gecko_nsFont_InitSystem(nsFont* dst, int32_t font_id,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -361,23 +361,18 @@ nsStyleBorder::nsStyleBorder(const nsSty
   , mFloatEdge(aSrc.mFloatEdge)
   , mBoxDecorationBreak(aSrc.mBoxDecorationBreak)
   , mComputedBorder(aSrc.mComputedBorder)
   , mBorder(aSrc.mBorder)
   , mTwipsPerPixel(aSrc.mTwipsPerPixel)
 {
   MOZ_COUNT_CTOR(nsStyleBorder);
   if (aSrc.mBorderColors) {
-    EnsureBorderColors();
-    for (int32_t i = 0; i < 4; i++) {
-      if (aSrc.mBorderColors[i]) {
-        mBorderColors[i] = aSrc.mBorderColors[i]->Clone();
-      } else {
-        mBorderColors[i] = nullptr;
-      }
+    NS_FOR_CSS_SIDES(side) {
+      CopyBorderColorsFrom(aSrc.mBorderColors[side], side);
     }
   }
 
   NS_FOR_CSS_SIDES(side) {
     mBorderStyle[side] = aSrc.mBorderStyle[side];
     mBorderColor[side] = aSrc.mBorderColor[side];
   }
 }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1157,16 +1157,24 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void ClearBorderColors(mozilla::Side aSide) {
     if (mBorderColors && mBorderColors[aSide]) {
       delete mBorderColors[aSide];
       mBorderColors[aSide] = nullptr;
     }
   }
 
+  void CopyBorderColorsFrom(const nsBorderColors* aSrcBorderColors, mozilla::Side aSide) {
+    if (aSrcBorderColors) {
+      EnsureBorderColors();
+      ClearBorderColors(aSide);
+      mBorderColors[aSide] = aSrcBorderColors->Clone();
+    }
+  }
+
   // Return whether aStyle is a visible style.  Invisible styles cause
   // the relevant computed border width to be 0.
   // Note that this does *not* consider the effects of 'border-image':
   // if border-style is none, but there is a loaded border image,
   // HasVisibleStyle will be false even though there *is* a border.
   bool HasVisibleStyle(mozilla::Side aSide) const
   {
     return IsVisibleBorderStyle(mBorderStyle[aSide]);
--- a/layout/style/test/stylo-failures.md
+++ b/layout/style/test/stylo-failures.md
@@ -100,19 +100,16 @@ to mochitest command.
   * test_bug887741_at-rules_in_declaration_lists.html `exception` [1]
 * Unimplemented \@font-face descriptors:
   * font-display bug 1355345
     * test_descriptor_storage.html `font-display` [5]
     * test_font_face_parser.html `font-display` [15]
   * test_font_face_parser.html `font-language-override`: bug 1355364 [8]
   * ... `font-feature-settings`: bug 1355366 [10]
 * test_font_face_parser.html `font-weight`: keyword values should be preserved in \@font-face [4]
-* unicode-range parsing bugs
-  * servo/rust-cssparser#133
-  * test_font_face_parser.html `4E00`: servo/rust-cssparser#135 [2]
 * @font-face support bug 1290237
   * test_descriptor_storage.html [1]
   * test_font_face_parser.html `@font-face` [8]
 * @namespace support:
   * test_namespace_rule.html: bug 1355715 [17]
 * test_dont_use_document_colors.html: support of disabling document color bug 1355716 [21]
 * test_exposed_prop_accessors.html: mainly various unsupported properties [*]
 * test_font_feature_values_parsing.html: \@font-feature-values support bug 1355721 [107]
@@ -129,24 +126,16 @@ to mochitest command.
   * test_initial_storage.html `grid` [*]
   * test_property_syntax_errors.html `grid`: actually there are issues with this [*]
   * test_value_storage.html `'grid` [*]
 * url value from decl setter bug 1330503
   * test_compute_data_with_start_struct.html `border-image-source` [2]
   * test_inherit_computation.html `border-image` [2]
   * test_initial_computation.html `border-image` [4]
 * Unimplemented prefixed properties:
-  * -moz-border-*-colors bug 1348173
-    * test_compute_data_with_start_struct.html `-colors` [8]
-    * test_inherit_computation.html `-colors` [8]
-    * test_inherit_storage.html `-colors` [12]
-    * test_initial_computation.html `-colors` [16]
-    * test_initial_storage.html `-colors` [24]
-    * test_value_storage.html `-colors` [96]
-    * test_shorthand_property_getters.html `-colors` [1]
   * -moz-force-broken-image-icon servo/servo#16001
     * test_compute_data_with_start_struct.html `-moz-force-broken-image-icon` [2]
     * test_inherit_computation.html `-moz-force-broken-image-icon` [2]
     * test_inherit_storage.html `-moz-force-broken-image-icon` [2]
     * test_initial_computation.html `-moz-force-broken-image-icon` [4]
     * test_initial_storage.html `-moz-force-broken-image-icon` [4]
     * test_value_storage.html `-moz-force-broken-image-icon` [4]
   * -moz-transform: need different parsing rules servo/servo#16003
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -1035,16 +1035,24 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEve
     // The scrollbar mediator is not the scroll frame.
     // That means this scroll frame has a custom scrollbar mediator.
     // That's not supported in the APZ codepath.
     if (!scrollFrame) {
       return;
     }
   }
 
+  nsIFrame* thumbFrame = mFrames.FirstChild();
+  if (!thumbFrame) {
+    return;
+  }
+  bool isHorizontal = IsXULHorizontal();
+  nsSize thumbSize = thumbFrame->GetSize();
+  nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height;
+
   mozilla::layers::FrameMetrics::ViewID scrollTargetId;
   bool hasID = nsLayoutUtils::FindIDFor(scrollableContent, &scrollTargetId);
   bool hasAPZView = hasID && (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
 
   if (!hasAPZView) {
     return;
   }
 
@@ -1060,18 +1068,20 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEve
 
   nsIPresShell* shell = PresContext()->PresShell();
   uint64_t inputblockId = InputAPZContext::GetInputBlockId();
   uint32_t presShellId = shell->GetPresShellId();
   AsyncDragMetrics dragMetrics(scrollTargetId, presShellId, inputblockId,
                                NSAppUnitsToFloatPixels(mDragStart,
                                  float(AppUnitsPerCSSPixel())),
                                sliderTrackCSS,
-                               IsXULHorizontal() ? AsyncDragMetrics::HORIZONTAL :
-                                                   AsyncDragMetrics::VERTICAL);
+                               NSAppUnitsToFloatPixels(thumbLength,
+                                 float(AppUnitsPerCSSPixel())),
+                               isHorizontal ? AsyncDragMetrics::HORIZONTAL :
+                                              AsyncDragMetrics::VERTICAL);
 
   if (!nsLayoutUtils::HasDisplayPort(scrollableContent)) {
     return;
   }
 
   // It's important to set this before calling nsIWidget::StartAsyncScrollbarDrag(),
   // because in some configurations, that can call AsyncScrollbarDragRejected()
   // synchronously, which clears the flag (and we want it to stay cleared in
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
@@ -174,17 +174,22 @@ public class ActionBarPresenter {
      */
     public void setTextLongClickListener(View.OnLongClickListener listener) {
         mTitleView.setOnLongClickListener(listener);
         mUrlView.setOnLongClickListener(listener);
     }
 
     private void initIndicator() {
         mActionBar.setDisplayHomeAsUpEnabled(true);
-        final Drawable icon = mActionBar.getThemedContext().getDrawable(R.drawable.ic_close_light);
+
+        @SuppressWarnings("deprecation")
+        final Drawable icon = mActionBar.getThemedContext()
+                .getResources()
+                .getDrawable(R.drawable.ic_close_light);
+
         DrawableCompat.setTint(icon, mTextPrimaryColor);
         mActionBar.setHomeAsUpIndicator(icon);
     }
 
     /**
      * To update appearance of CustomView of ActionBar, includes its icon, title and url text.
      *
      * @param identity SiteIdentity for current website. Could be null if don't want to show icon.
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -236,17 +236,20 @@ public class CustomTabsActivity extends 
                         public void onClick(View v) {
                             onActionButtonClicked();
                         }
                     });
         }
 
         // insert an action button for menu. click it to show popup menu
         popupMenu = createCustomPopupMenu();
-        actionBarPresenter.addActionButton(menu, getDrawable(R.drawable.ab_menu), true)
+
+        @SuppressWarnings("deprecation")
+        Drawable icon = getResources().getDrawable(R.drawable.ab_menu);
+        actionBarPresenter.addActionButton(menu, icon, true)
                 .setOnClickListener(new View.OnClickListener() {
                     @Override
                     public void onClick(View anchor) {
                         popupMenu.setAnchor(anchor);
                         popupMenu.show();
                     }
                 });
 
--- a/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
@@ -56,16 +56,22 @@ import java.util.Map;
  */
 @ReflectionTarget
 public class PushService implements BundleEventListener {
     private static final String LOG_TAG = "GeckoPushService";
 
     public static final String SERVICE_WEBPUSH = "webpush";
     public static final String SERVICE_FXA = "fxa";
 
+    public static final double ERROR_GCM_DISABLED = 2154627078L; // = NS_ERROR_DOM_PUSH_GCM_DISABLED
+
+    public static final String REPLY_BUNDLE_KEY_ERROR = "error";
+    public static final String ERROR_BUNDLE_KEY_MESSAGE = "message";
+    public static final String ERROR_BUNDLE_KEY_RESULT = "result";
+
     private static PushService sInstance;
 
     private static final String[] GECKO_EVENTS = new String[] {
             "PushServiceAndroidGCM:Configure",
             "PushServiceAndroidGCM:DumpRegistration",
             "PushServiceAndroidGCM:DumpSubscriptions",
             "PushServiceAndroidGCM:Initialized",
             "PushServiceAndroidGCM:Uninitialized",
@@ -165,17 +171,17 @@ public class PushService implements Bund
 
             // This decision will be re-addressed as part of Bug 1346061.
             if (!State.StateLabel.Married.equals(fxAccountState.getStateLabel())) {
                 Log.i(LOG_TAG, "FxA account not in Married state, not proceeding with registration renewal");
                 return;
             }
 
             // We'll obtain a new subscription as part of device registration.
-            if (FxAccountDeviceRegistrator.needToRenewRegistration(fxAccount.getDeviceRegistrationTimestamp())) {
+            if (FxAccountDeviceRegistrator.shouldRenewRegistration(fxAccount)) {
                 Log.i(LOG_TAG, "FxA device needs registration renewal");
                 FxAccountDeviceRegistrator.renewRegistration(context);
             }
         } catch (Exception e) {
             Log.e(LOG_TAG, "Got exception during startup; ignoring.", e);
             return;
         }
     }
@@ -462,17 +468,23 @@ public class PushService implements Bund
                 callback.sendSuccess(millis);
                 return;
             }
         } catch (GcmTokenClient.NeedsGooglePlayServicesException e) {
             // TODO: improve this.  Can we find a point where the user is *definitely* interacting
             // with the WebPush?  Perhaps we can show a dialog when interacting with the Push
             // permissions, and then be more aggressive showing this notification when we have
             // registrations and subscriptions that can't be advanced.
-            callback.sendError("To handle event [" + event + "], user interaction is needed to enable Google Play Services.");
+            String msg = "To handle event [" + event + "], user interaction is needed to enable Google Play Services.";
+            GeckoBundle reply = new GeckoBundle();
+            GeckoBundle error = new GeckoBundle();
+            error.putString(ERROR_BUNDLE_KEY_MESSAGE, msg);
+            error.putDouble(ERROR_BUNDLE_KEY_RESULT, ERROR_GCM_DISABLED);
+            reply.putBundle(REPLY_BUNDLE_KEY_ERROR, error);
+            callback.sendError(reply);
         }
     }
 
     private void processComponentState(@NonNull GeckoComponent component, boolean isReady) {
         if (component == GeckoComponent.FxAccountsPush) {
             isReadyFxAccountsPush = isReady;
 
         } else if (component == GeckoComponent.PushServiceAndroidGCM) {
--- a/mobile/android/components/FxAccountsPush.js
+++ b/mobile/android/components/FxAccountsPush.js
@@ -1,16 +1,14 @@
 /* jshint moz: true, esnext: true */
 /* 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/. */
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Messaging.jsm");
 const {
   PushCrypto,
   getCryptoParams,
 } = Cu.import("resource://gre/modules/PushCrypto.jsm", {});
@@ -55,32 +53,38 @@ FxAccountsPush.prototype = {
       PushService.subscribe(FXA_PUSH_SCOPE,
         Services.scriptSecurityManager.getSystemPrincipal(),
         (result, subscription) => {
           if (Components.isSuccessCode(result)) {
             Log.d("FxAccountsPush got subscription");
             resolve(subscription);
           } else {
             Log.w("FxAccountsPush failed to subscribe", result);
-            reject(new Error("FxAccountsPush failed to subscribe"));
+            const err = new Error("FxAccountsPush failed to subscribe");
+            err.result = result;
+            reject(err);
           }
         });
     })
     .then(subscription => {
       EventDispatcher.instance.sendRequest({
         type: "FxAccountsPush:Subscribe:Response",
         subscription: {
           pushCallback: subscription.endpoint,
           pushPublicKey: urlsafeBase64Encode(subscription.getKey('p256dh')),
           pushAuthKey: urlsafeBase64Encode(subscription.getKey('auth'))
         }
       });
     })
     .catch(err => {
       Log.i("Error when registering FxA push endpoint " + err);
+      EventDispatcher.instance.sendRequest({
+        type: "FxAccountsPush:Subscribe:Response",
+        error: err.result.toString() // Convert to string because the GeckoBundle can't getLong();
+      });
     });
   },
 
   _unsubscribe() {
     Log.i("FxAccountsPush _unsubscribe");
     return new Promise((resolve) => {
       PushService.unsubscribe(FXA_PUSH_SCOPE,
         Services.scriptSecurityManager.getSystemPrincipal(),
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountDevice.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountDevice.java
@@ -30,26 +30,16 @@ public class FxAccountDevice {
     this.id = id;
     this.type = type;
     this.isCurrentDevice = isCurrentDevice;
     this.pushCallback = pushCallback;
     this.pushPublicKey = pushPublicKey;
     this.pushAuthKey = pushAuthKey;
   }
 
-  public static FxAccountDevice forRegister(String name, String type, String pushCallback,
-                                            String pushPublicKey, String pushAuthKey) {
-    return new FxAccountDevice(name, null, type, null, pushCallback, pushPublicKey, pushAuthKey);
-  }
-
-  public static FxAccountDevice forUpdate(String id, String name, String pushCallback,
-                                          String pushPublicKey, String pushAuthKey) {
-    return new FxAccountDevice(name, id, null, null, pushCallback, pushPublicKey, pushAuthKey);
-  }
-
   public static FxAccountDevice fromJson(ExtendedJSONObject json) {
     String name = json.getString(JSON_KEY_NAME);
     String id = json.getString(JSON_KEY_ID);
     String type = json.getString(JSON_KEY_TYPE);
     Boolean isCurrentDevice = json.getBoolean(JSON_KEY_ISCURRENTDEVICE);
     String pushCallback = json.getString(JSON_KEY_PUSH_CALLBACK);
     String pushPublicKey = json.getString(JSON_KEY_PUSH_PUBLICKEY);
     String pushAuthKey = json.getString(JSON_KEY_PUSH_AUTHKEY);
@@ -73,9 +63,52 @@ public class FxAccountDevice {
     if (this.pushPublicKey != null) {
       body.put(JSON_KEY_PUSH_PUBLICKEY, this.pushPublicKey);
     }
     if (this.pushAuthKey != null) {
       body.put(JSON_KEY_PUSH_AUTHKEY, this.pushAuthKey);
     }
     return body;
   }
+
+  public static class Builder {
+    private String id;
+    private String name;
+    private String type;
+    private Boolean isCurrentDevice;
+    private String pushCallback;
+    private String pushPublicKey;
+    private String pushAuthKey;
+
+    public void id(String id) {
+      this.id = id;
+    }
+
+    public void name(String name) {
+      this.name = name;
+    }
+
+    public void type(String type) {
+      this.type = type;
+    }
+
+    public void isCurrentDevice() {
+      this.isCurrentDevice = Boolean.TRUE;
+    }
+
+    public void pushCallback(String pushCallback) {
+      this.pushCallback = pushCallback;
+    }
+
+    public void pushPublicKey(String pushPublicKey) {
+      this.pushPublicKey = pushPublicKey;
+    }
+
+    public void pushAuthKey(String pushAuthKey) {
+      this.pushAuthKey = pushAuthKey;
+    }
+
+    public FxAccountDevice build() {
+      return new FxAccountDevice(this.name, this.id, this.type, this.isCurrentDevice,
+                                 this.pushCallback, this.pushPublicKey, this.pushAuthKey);
+    }
+  }
 }
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountDeviceRegistrator.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountDeviceRegistrator.java
@@ -1,17 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.fxa;
 
 import android.content.Context;
 import android.content.Intent;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountClient;
 import org.mozilla.gecko.background.fxa.FxAccountClient20;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.AccountStatusResponse;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.RequestDelegate;
@@ -29,67 +31,89 @@ import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.GeneralSecurityException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 /* This class provides a way to register the current device against FxA
  * and also stores the registration details in the Android FxAccount.
- * This should be used in a state where we possess a sessionToken, most likely the Married state.
+ * This should be used in a state where we possess a sessionToken, most likely the Engaged/Married states.
  */
 public class FxAccountDeviceRegistrator implements BundleEventListener {
   private static final String LOG_TAG = "FxADeviceRegistrator";
 
   // The autopush endpoint expires stale channel subscriptions every 30 days (at a set time during
   // the month, although we don't depend on this). To avoid the FxA service channel silently
   // expiring from underneath us, we unsubscribe and resubscribe every 21 days.
   // Note that this simple schedule means that we might unsubscribe perfectly valid (but old)
   // subscriptions. This will be improved as part of Bug 1345651.
-  private static final long TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS = 21 * 24 * 60 * 60 * 1000L;
+  @VisibleForTesting
+  static final long TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS = 21 * 24 * 60 * 60 * 1000L;
+
+  @VisibleForTesting
+  static final long RETRY_TIME_AFTER_GCM_DISABLED_ERROR = 15 * 24 * 60 * 60 * 1000L;
+
+
+  public static final String PUSH_SUBSCRIPTION_REPLY_BUNDLE_KEY_ERROR = "error";
+  @VisibleForTesting
+  static final long ERROR_GCM_DISABLED = 2154627078L; // = NS_ERROR_DOM_PUSH_GCM_DISABLED
 
   // The current version of the device registration, we use this to re-register
   // devices after we update what we send on device registration.
-  public static final Integer DEVICE_REGISTRATION_VERSION = 2;
+  @VisibleForTesting
+  static final Integer DEVICE_REGISTRATION_VERSION = 2;
 
   private static FxAccountDeviceRegistrator instance;
   private final WeakReference<Context> context;
 
   private FxAccountDeviceRegistrator(Context appContext) {
-    this.context = new WeakReference<Context>(appContext);
+    this.context = new WeakReference<>(appContext);
   }
 
   private static FxAccountDeviceRegistrator getInstance(Context appContext) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
     if (instance == null) {
-      FxAccountDeviceRegistrator tempInstance = new FxAccountDeviceRegistrator(appContext);
+      final FxAccountDeviceRegistrator tempInstance = new FxAccountDeviceRegistrator(appContext);
       tempInstance.setupListeners(); // Set up listener for FxAccountPush:Subscribe:Response
       instance = tempInstance;
     }
     return instance;
   }
 
-  public static boolean needToRenewRegistration(final long timestamp) {
+  public static boolean shouldRegister(final AndroidFxAccount fxAccount) {
+    if (fxAccount.getDeviceRegistrationVersion() != FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION ||
+            TextUtils.isEmpty(fxAccount.getDeviceId())) {
+      return true;
+    }
+    // At this point, we have a working up-to-date registration, but it might be a partial one
+    // (no push registration).
+    return fxAccount.getDevicePushRegistrationError() == ERROR_GCM_DISABLED &&
+           (System.currentTimeMillis() - fxAccount.getDevicePushRegistrationErrorTime()) > RETRY_TIME_AFTER_GCM_DISABLED_ERROR;
+  }
+
+  public static boolean shouldRenewRegistration(final AndroidFxAccount fxAccount) {
+    final long deviceRegistrationTimestamp = fxAccount.getDeviceRegistrationTimestamp();
     // NB: we're comparing wall clock to wall clock, at different points in time.
     // It's possible that wall clocks have changed, and our comparison will be meaningless.
     // However, this happens in the context of a sync, and we won't be able to sync anyways if our
     // wall clock deviates too much from time on the server.
-    return (System.currentTimeMillis() - timestamp) > TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS;
+    return (System.currentTimeMillis() - deviceRegistrationTimestamp) > TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS;
   }
 
   public static void register(Context context) {
-    Context appContext = context.getApplicationContext();
+    final Context appContext = context.getApplicationContext();
     try {
       getInstance(appContext).beginRegistration(appContext);
     } catch (Exception e) {
       Log.e(LOG_TAG, "Could not start FxA device registration", e);
     }
   }
 
   public static void renewRegistration(Context context) {
-    Context appContext = context.getApplicationContext();
+    final Context appContext = context.getApplicationContext();
     try {
       getInstance(appContext).beginRegistrationRenewal(appContext);
     } catch (Exception e) {
       Log.e(LOG_TAG, "Could not start FxA device re-registration", e);
     }
   }
 
   private void beginRegistration(Context context) {
@@ -117,60 +141,76 @@ public class FxAccountDeviceRegistrator 
     final AndroidFxAccount fxAccount = AndroidFxAccount.fromContext(context);
     intent.putExtra("org.mozilla.gecko.intent.PROFILE_NAME", fxAccount.getProfile());
     return intent;
   }
 
   @Override
   public void handleMessage(String event, GeckoBundle message, EventCallback callback) {
     if ("FxAccountsPush:Subscribe:Response".equals(event)) {
-      doFxaRegistration(message.getBundle("subscription"));
+      handlePushSubscriptionResponse(message);
     } else {
       Log.e(LOG_TAG, "No action defined for " + event);
     }
   }
 
-  private void doFxaRegistration(GeckoBundle subscription) {
+  private void handlePushSubscriptionResponse(final GeckoBundle message) {
+    // Make sure the context has not been gc'd during the push registration
+    // and the FxAccount still exists.
     final Context context = this.context.get();
-    if (this.context == null) {
+    if (context == null) {
       throw new IllegalStateException("Application context has been gc'ed");
     }
-    doFxaRegistration(context, subscription, true);
-  }
-
-  private static void doFxaRegistration(final Context context, final GeckoBundle subscription, final boolean allowRecursion) {
-    String pushCallback = subscription.getString("pushCallback");
-    String pushPublicKey = subscription.getString("pushPublicKey");
-    String pushAuthKey = subscription.getString("pushAuthKey");
-
     final AndroidFxAccount fxAccount = AndroidFxAccount.fromContext(context);
     if (fxAccount == null) {
       Log.e(LOG_TAG, "AndroidFxAccount is null");
       return;
     }
+
+    fxAccount.resetDevicePushRegistrationError();
+    final long error = getSubscriptionReplyError(message);
+
+    final FxAccountDevice device;
+    if (error == 0L) {
+      Log.i(LOG_TAG, "Push registration succeeded. Beginning normal FxA Registration.");
+      device = buildFxAccountDevice(context, fxAccount, message.getBundle("subscription"));
+    } else {
+      fxAccount.setDevicePushRegistrationError(error, System.currentTimeMillis());
+      Log.i(LOG_TAG, "Push registration failed. Beginning degraded FxA Registration.");
+      device = buildFxAccountDevice(context, fxAccount);
+    }
+
+    doFxaRegistration(context, fxAccount, device, true);
+  }
+
+  private long getSubscriptionReplyError(final GeckoBundle message) {
+    String errorStr = message.getString(PUSH_SUBSCRIPTION_REPLY_BUNDLE_KEY_ERROR);
+    if (TextUtils.isEmpty(errorStr)) {
+      return 0L;
+    }
+    return Long.parseLong(errorStr);
+  }
+
+  private static void doFxaRegistration(final Context context, final AndroidFxAccount fxAccount,
+                                        final FxAccountDevice device, final boolean allowRecursion) {
     final byte[] sessionToken;
     try {
       sessionToken = fxAccount.getState().getSessionToken();
     } catch (State.NotASessionTokenState e) {
       Log.e(LOG_TAG, "Could not get a session token", e);
       return;
     }
-    final FxAccountDevice device;
-    String deviceId = fxAccount.getDeviceId();
-    String clientName = getClientName(fxAccount, context);
-    if (TextUtils.isEmpty(deviceId)) {
+
+    if (device.id == null) {
       Log.i(LOG_TAG, "Attempting registration for a new device");
-      device = FxAccountDevice.forRegister(clientName, "mobile", pushCallback, pushPublicKey, pushAuthKey);
     } else {
       Log.i(LOG_TAG, "Attempting registration for an existing device");
-      Logger.pii(LOG_TAG, "Device ID: " + deviceId);
-      device = FxAccountDevice.forUpdate(deviceId, clientName, pushCallback, pushPublicKey, pushAuthKey);
     }
 
-    ExecutorService executor = Executors.newSingleThreadExecutor(); // Not called often, it's okay to spawn another thread
+    final ExecutorService executor = Executors.newSingleThreadExecutor(); // Not called often, it's okay to spawn another thread
     final FxAccountClient20 fxAccountClient =
             new FxAccountClient20(fxAccount.getAccountServerURI(), executor);
     fxAccountClient.registerOrUpdateDevice(sessionToken, device, new RequestDelegate<FxAccountDevice>() {
       @Override
       public void handleError(Exception e) {
         Log.e(LOG_TAG, "Error while updating a device registration: ", e);
         fxAccount.setDeviceRegistrationTimestamp(0L);
       }
@@ -180,48 +220,83 @@ public class FxAccountDeviceRegistrator 
         Log.e(LOG_TAG, "Error while updating a device registration: ", error);
 
         fxAccount.setDeviceRegistrationTimestamp(0L);
 
         if (error.httpStatusCode == 400) {
           if (error.apiErrorNumber == FxAccountRemoteError.UNKNOWN_DEVICE) {
             recoverFromUnknownDevice(fxAccount);
           } else if (error.apiErrorNumber == FxAccountRemoteError.DEVICE_SESSION_CONFLICT) {
-            recoverFromDeviceSessionConflict(error, fxAccountClient, sessionToken, fxAccount, context,
-                    subscription, allowRecursion);
+            // This can happen if a device was already registered using our session token, and we
+            // tried to create a new one (no id field).
+            recoverFromDeviceSessionConflict(error, fxAccountClient, sessionToken, fxAccount, device,
+                    context, allowRecursion);
           }
         } else
         if (error.httpStatusCode == 401
                 && error.apiErrorNumber == FxAccountRemoteError.INVALID_AUTHENTICATION_TOKEN) {
           handleTokenError(error, fxAccountClient, fxAccount);
         } else {
           logErrorAndResetDeviceRegistrationVersionAndTimestamp(error, fxAccount);
         }
       }
 
       @Override
       public void handleSuccess(FxAccountDevice result) {
         Log.i(LOG_TAG, "Device registration complete");
         Logger.pii(LOG_TAG, "Registered device ID: " + result.id);
+        Log.i(LOG_TAG, "Setting DEVICE_REGISTRATION_VERSION to " + DEVICE_REGISTRATION_VERSION);
         fxAccount.setFxAUserData(result.id, DEVICE_REGISTRATION_VERSION, System.currentTimeMillis());
       }
     });
   }
 
+  private static FxAccountDevice buildFxAccountDevice(Context context, AndroidFxAccount fxAccount) {
+    return makeFxADeviceCommonBuilder(context, fxAccount).build();
+  }
+
+  private static FxAccountDevice buildFxAccountDevice(Context context, AndroidFxAccount fxAccount, @NonNull GeckoBundle subscription) {
+    final FxAccountDevice.Builder builder = makeFxADeviceCommonBuilder(context, fxAccount);
+    final String pushCallback = subscription.getString("pushCallback");
+    final String pushPublicKey = subscription.getString("pushPublicKey");
+    final String pushAuthKey = subscription.getString("pushAuthKey");
+    if (!TextUtils.isEmpty(pushCallback) && !TextUtils.isEmpty(pushPublicKey) &&
+        !TextUtils.isEmpty(pushAuthKey)) {
+      builder.pushCallback(pushCallback);
+      builder.pushPublicKey(pushPublicKey);
+      builder.pushAuthKey(pushAuthKey);
+    }
+    return builder.build();
+  }
+
+  // Do not call this directly, use buildFxAccountDevice instead.
+  private static FxAccountDevice.Builder makeFxADeviceCommonBuilder(Context context, AndroidFxAccount fxAccount) {
+    final String deviceId = fxAccount.getDeviceId();
+    final String clientName = getClientName(fxAccount, context);
+
+    final FxAccountDevice.Builder builder = new FxAccountDevice.Builder();
+    builder.name(clientName);
+    builder.type("mobile");
+    if (!TextUtils.isEmpty(deviceId)) {
+      builder.id(deviceId);
+    }
+    return builder;
+  }
+
   private static void logErrorAndResetDeviceRegistrationVersionAndTimestamp(
       final FxAccountClientRemoteException error, final AndroidFxAccount fxAccount) {
     Log.e(LOG_TAG, "Device registration failed", error);
     fxAccount.resetDeviceRegistrationVersion();
     fxAccount.setDeviceRegistrationTimestamp(0L);
   }
 
   @Nullable
   private static String getClientName(final AndroidFxAccount fxAccount, final Context context) {
     try {
-      SharedPreferencesClientsDataDelegate clientsDataDelegate =
+      final SharedPreferencesClientsDataDelegate clientsDataDelegate =
           new SharedPreferencesClientsDataDelegate(fxAccount.getSyncPrefs(), context);
       return clientsDataDelegate.getClientName();
     } catch (UnsupportedEncodingException | GeneralSecurityException e) {
       Log.e(LOG_TAG, "Unable to get client name.", e);
       return null;
     }
   }
 
@@ -237,17 +312,17 @@ public class FxAccountDeviceRegistrator 
       }
 
       @Override
       public void handleFailure(FxAccountClientRemoteException e) {
       }
 
       @Override
       public void handleSuccess(AccountStatusResponse result) {
-        State doghouseState = fxAccount.getState().makeDoghouseState();
+        final State doghouseState = fxAccount.getState().makeDoghouseState();
         if (!result.exists) {
           Log.i(LOG_TAG, "token invalidated because the account no longer exists");
           // TODO: Should be in a "I have an Android account, but the FxA is gone." State.
           // This will do for now..
           fxAccount.setState(doghouseState);
           return;
         }
         Log.e(LOG_TAG, "sessionToken invalid");
@@ -263,19 +338,22 @@ public class FxAccountDeviceRegistrator 
 
   /**
    * Will call delegate#complete in all cases
    */
   private static void recoverFromDeviceSessionConflict(final FxAccountClientRemoteException error,
                                                        final FxAccountClient fxAccountClient,
                                                        final byte[] sessionToken,
                                                        final AndroidFxAccount fxAccount,
+                                                       final FxAccountDevice device,
                                                        final Context context,
-                                                       final GeckoBundle subscription,
                                                        final boolean allowRecursion) {
+    // Recovery strategy: re-try a registration, UPDATING (instead of creating) the device.
+    // We do that by finding the device ID who conflicted with us and try a registration update
+    // using that id.
     Log.w(LOG_TAG, "device session conflict, attempting to ascertain the correct device id");
     fxAccountClient.deviceList(sessionToken, new RequestDelegate<FxAccountDevice[]>() {
       private void onError() {
         Log.e(LOG_TAG, "failed to recover from device-session conflict");
         logErrorAndResetDeviceRegistrationVersionAndTimestamp(error, fxAccount);
       }
 
       @Override
@@ -285,35 +363,39 @@ public class FxAccountDeviceRegistrator 
 
       @Override
       public void handleFailure(FxAccountClientRemoteException e) {
         onError();
       }
 
       @Override
       public void handleSuccess(FxAccountDevice[] devices) {
-        for (FxAccountDevice device : devices) {
-          if (device.isCurrentDevice) {
-            fxAccount.setFxAUserData(device.id, 0, 0L); // Reset device registration version/timestamp
-            if (!allowRecursion) {
-              Log.d(LOG_TAG, "Failure to register a device on the second try");
-              break;
-            }
-            doFxaRegistration(context, subscription, false);
-            return;
+        for (final FxAccountDevice fxaDevice : devices) {
+          if (!fxaDevice.isCurrentDevice) {
+            continue;
           }
+          fxAccount.setFxAUserData(fxaDevice.id, 0, 0L); // Reset device registration version/timestamp
+          if (!allowRecursion) {
+            Log.d(LOG_TAG, "Failure to register a device on the second try");
+            break;
+          }
+          final FxAccountDevice updatedDevice = new FxAccountDevice(device.name, fxaDevice.id, device.type,
+                                                                    device.isCurrentDevice, device.pushCallback,
+                                                                    device.pushPublicKey, device.pushAuthKey);
+          doFxaRegistration(context, fxAccount, updatedDevice, false);
+          return;
         }
         onError();
       }
     });
   }
 
   private void setupListeners() throws ClassNotFoundException, NoSuchMethodException,
           InvocationTargetException, IllegalAccessException {
     // We have no choice but to use reflection here, sorry :(
-    Class<?> eventDispatcher = Class.forName("org.mozilla.gecko.EventDispatcher");
-    Method getInstance = eventDispatcher.getMethod("getInstance");
-    Object instance = getInstance.invoke(null);
-    Method registerBackgroundThreadListener = eventDispatcher.getMethod("registerBackgroundThreadListener",
+    final Class<?> eventDispatcher = Class.forName("org.mozilla.gecko.EventDispatcher");
+    final Method getInstance = eventDispatcher.getMethod("getInstance");
+    final Object instance = getInstance.invoke(null);
+    final Method registerBackgroundThreadListener = eventDispatcher.getMethod("registerBackgroundThreadListener",
             BundleEventListener.class, String[].class);
     registerBackgroundThreadListener.invoke(instance, this, new String[] { "FxAccountsPush:Subscribe:Response" });
   }
 }
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AndroidFxAccount.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AndroidFxAccount.java
@@ -10,17 +10,16 @@ import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ResultReceiver;
-import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.content.LocalBroadcastManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import org.mozilla.gecko.background.common.GlobalConstants;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
@@ -34,16 +33,18 @@ import org.mozilla.gecko.fxa.sync.FxAcco
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
+import java.text.NumberFormat;
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Semaphore;
 
@@ -75,16 +76,18 @@ public class AndroidFxAccount {
   public static final String BUNDLE_KEY_BUNDLE_VERSION = "version";
   public static final String BUNDLE_KEY_STATE_LABEL = "stateLabel";
   public static final String BUNDLE_KEY_STATE = "state";
   public static final String BUNDLE_KEY_PROFILE_JSON = "profile";
 
   public static final String ACCOUNT_KEY_DEVICE_ID = "deviceId";
   public static final String ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION = "deviceRegistrationVersion";
   private static final String ACCOUNT_KEY_DEVICE_REGISTRATION_TIMESTAMP = "deviceRegistrationTimestamp";
+  private static final String ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR = "devicePushRegistrationError";
+  private static final String ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR_TIME = "devicePushRegistrationErrorTime";
 
   // Account authentication token type for fetching account profile.
   public static final String PROFILE_OAUTH_TOKEN_TYPE = "oauth::profile";
 
   // Services may request OAuth tokens from the Firefox Account dynamically.
   // Each such token is prefixed with "oauth::" and a service-dependent scope.
   // Such tokens should be destroyed when the account is removed from the device.
   // This list collects all the known "oauth::" token types in order to delete them when necessary.
@@ -797,50 +800,49 @@ public class AndroidFxAccount {
         intent.putExtra(FxAccountProfileService.KEY_AUTH_TOKEN, authToken);
         intent.putExtra(FxAccountProfileService.KEY_PROFILE_SERVER_URI, getProfileServerURI());
         intent.putExtra(FxAccountProfileService.KEY_RESULT_RECEIVER, new ProfileResultReceiver(new Handler()));
         context.startService(intent);
       }
     });
   }
 
+  @SuppressWarnings("unchecked")
+  private <T extends Number> T getUserDataNumber(String key, T defaultValue) {
+    final String numStr = accountManager.getUserData(account, key);
+    if (TextUtils.isEmpty(numStr)) {
+      return defaultValue;
+    }
+    try {
+      return (T) NumberFormat.getInstance().parse(numStr);
+    } catch (ParseException e) {
+      Logger.warn(LOG_TAG, "Couldn't parse " + key + "; defaulting to 0L.", e);
+      return defaultValue;
+    }
+  }
+
   @Nullable
   public synchronized String getDeviceId() {
     return accountManager.getUserData(account, ACCOUNT_KEY_DEVICE_ID);
   }
 
-  @NonNull
   public synchronized int getDeviceRegistrationVersion() {
-    String versionStr = accountManager.getUserData(account, ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION);
-    if (TextUtils.isEmpty(versionStr)) {
-      return 0;
-    } else {
-      try {
-        return Integer.parseInt(versionStr);
-      } catch (NumberFormatException ex) {
-        return 0;
-      }
-    }
+    return getUserDataNumber(ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION, 0);
   }
 
   public synchronized long getDeviceRegistrationTimestamp() {
-    final String timestampStr = accountManager.getUserData(account, ACCOUNT_KEY_DEVICE_REGISTRATION_TIMESTAMP);
-
-    if (TextUtils.isEmpty(timestampStr)) {
-      return 0L;
-    }
+    return getUserDataNumber(ACCOUNT_KEY_DEVICE_REGISTRATION_TIMESTAMP, 0L);
+  }
 
-    // Long.parseLong might throw; while it's not expected that this might happen, let's not risk
-    // crashing here as this method will be called on startup.
-    try {
-      return Long.parseLong(timestampStr);
-    } catch (NumberFormatException e) {
-      Logger.warn(LOG_TAG, "Couldn't parse deviceRegistrationTimestamp; defaulting to 0L.", e);
-      return 0L;
-    }
+  public synchronized long getDevicePushRegistrationError() {
+    return getUserDataNumber(ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR, 0L);
+  }
+
+  public synchronized long getDevicePushRegistrationErrorTime() {
+    return getUserDataNumber(ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR_TIME, 0L);
   }
 
   public synchronized void setDeviceId(String id) {
     accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_ID, id);
   }
 
   public synchronized void setDeviceRegistrationVersion(int deviceRegistrationVersion) {
     accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION,
@@ -859,16 +861,25 @@ public class AndroidFxAccount {
   public synchronized void setFxAUserData(String id, int deviceRegistrationVersion, long timestamp) {
     accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_ID, id);
     accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION,
             Integer.toString(deviceRegistrationVersion));
     accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_REGISTRATION_TIMESTAMP,
             Long.toString(timestamp));
   }
 
+  public synchronized void setDevicePushRegistrationError(long error, long errorTimeMs) {
+    accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR, Long.toString(error));
+    accountManager.setUserData(account, ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR_TIME, Long.toString(errorTimeMs));
+  }
+
+  public synchronized void resetDevicePushRegistrationError() {
+    setDevicePushRegistrationError(0L, 0l);
+  }
+
   @SuppressLint("ParcelCreator") // The CREATOR field is defined in the super class.
   private class ProfileResultReceiver extends ResultReceiver {
     public ProfileResultReceiver(Handler handler) {
       super(handler);
     }
 
     @Override
     protected void onReceiveResult(int resultCode, Bundle bundle) {
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/sync/FxAccountSyncAdapter.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/sync/FxAccountSyncAdapter.java
@@ -404,23 +404,22 @@ public class FxAccountSyncAdapter extend
     tokenServerclient.getTokenFromBrowserIDAssertion(assertion, true, clientState, delegate);
   }
 
   public void maybeRegisterDevice(Context context, AndroidFxAccount fxAccount) {
     // Register the device if necessary (asynchronous, in another thread).
     // As part of device registration, we obtain a PushSubscription, register our push endpoint
     // with FxA, and update account data with fxaDeviceId, which is part of our synced
     // clients record.
-    if (fxAccount.getDeviceRegistrationVersion() != FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION
-            || TextUtils.isEmpty(fxAccount.getDeviceId())) {
+    if (FxAccountDeviceRegistrator.shouldRegister(fxAccount)) {
       FxAccountDeviceRegistrator.register(context);
       // We might need to re-register periodically to ensure our FxA push subscription is valid.
       // This involves unsubscribing, subscribing and updating remote FxA device record with
       // new push subscription information.
-    } else if (FxAccountDeviceRegistrator.needToRenewRegistration(fxAccount.getDeviceRegistrationTimestamp())) {
+    } else if (FxAccountDeviceRegistrator.shouldRenewRegistration(fxAccount)) {
       FxAccountDeviceRegistrator.renewRegistration(context);
     }
   }
 
   /**
    * A trivial Sync implementation that does not cache client keys,
    * certificates, or tokens.
    *
new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/fxa/TestFxAccountDeviceRegistrator.java
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.gecko.fxa;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mozilla.gecko.background.testhelpers.TestRunner;
+import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+@RunWith(TestRunner.class)
+public class TestFxAccountDeviceRegistrator {
+
+    @Mock
+    AndroidFxAccount fxAccount;
+
+    @Before
+    public void init() {
+        // Process Mockito annotations
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void shouldRegister() {
+        // Assuming there is no previous push registration errors recorded:
+        when(fxAccount.getDevicePushRegistrationError()).thenReturn(0L);
+        when(fxAccount.getDevicePushRegistrationErrorTime()).thenReturn(0L);
+
+        // Should return false if the device registration version is up-to-date and a device ID is stored.
+        // (general case after a successful device registration)
+        when(fxAccount.getDeviceRegistrationVersion()).thenReturn(FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION);
+        when(fxAccount.getDeviceId()).thenReturn("bogusdeviceid");
+        assertFalse(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return true if the device registration version is up-to-date but no device ID is stored.
+        // (data mangling)
+        when(fxAccount.getDeviceRegistrationVersion()).thenReturn(FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION);
+        when(fxAccount.getDeviceId()).thenReturn(null);
+        assertTrue(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return true if the device ID is stored but no device registration version can be found.
+        // (data mangling)
+        when(fxAccount.getDeviceRegistrationVersion()).thenReturn(0);
+        when(fxAccount.getDeviceId()).thenReturn("bogusid");
+        assertTrue(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return true if the device registration version is too old.
+        // (code update pushed)
+        when(fxAccount.getDeviceRegistrationVersion()).thenReturn(FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION - 1);
+        assertTrue(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return true if the device registration is OK, but we didn't get a push subscription because
+        // Google Play Services were unavailable at the time and the retry delay is passed.
+        when(fxAccount.getDeviceRegistrationVersion()).thenReturn(FxAccountDeviceRegistrator.DEVICE_REGISTRATION_VERSION);
+        when(fxAccount.getDevicePushRegistrationError()).thenReturn(FxAccountDeviceRegistrator.ERROR_GCM_DISABLED);
+        when(fxAccount.getDevicePushRegistrationErrorTime()).thenReturn(System.currentTimeMillis() -
+                                                                        FxAccountDeviceRegistrator.RETRY_TIME_AFTER_GCM_DISABLED_ERROR - 1);
+        assertTrue(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return false if the device registration is OK, but we didn't get a push subscription because
+        // Google Play Services were unavailable at the time and the retry delay has not passed.
+        // We assume that RETRY_TIME_AFTER_GCM_DISABLED_ERROR is longer than the time it takes to execute this test :)
+        when(fxAccount.getDevicePushRegistrationErrorTime()).thenReturn(System.currentTimeMillis());
+        assertFalse(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+
+        // Should return false if the device registration is OK, but we didn't get a push subscription because
+        // an unknown error happened at the time.
+        when(fxAccount.getDevicePushRegistrationError()).thenReturn(12345L);
+        assertFalse(FxAccountDeviceRegistrator.shouldRegister(fxAccount));
+    }
+
+    @Test
+    public void shouldRenewRegistration() {
+        // Should return true if our last push registration was done a day before our expiration threshold.
+        when(fxAccount.getDeviceRegistrationTimestamp()).thenReturn(System.currentTimeMillis() -
+                                                                    FxAccountDeviceRegistrator.TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS -
+                                                                    1 * 24 * 60 * 60 * 1000L);
+
+        // Should return false if our last push registration is recent enough.
+        // We assume that TIME_BETWEEN_CHANNEL_REGISTRATION_IN_MILLIS is longer than a day + the time it takes to run this test.
+        when(fxAccount.getDeviceRegistrationTimestamp()).thenReturn(System.currentTimeMillis() -
+                                                                    1 * 24 * 60 * 60 * 1000L);
+    }
+}
--- a/services/cloudsync/tests/xpcshell/test_bookmarks.js
+++ b/services/cloudsync/tests/xpcshell/test_bookmarks.js
@@ -9,39 +9,60 @@ function run_test() {
   run_next_test();
 }
 
 add_task(function* test_merge_bookmarks_flat() {
   try {
     let rootFolder = yield CloudSync().bookmarks.getRootFolder("TEST");
     ok(rootFolder.id, "root folder id is ok");
 
-    let items = [
-      {"id":"G_UL4ZhOyX8m", "type":rootFolder.BOOKMARK, "title":"reddit: the front page of the internet 1", "uri":"http://www.reddit.com", index:2},
-      {"id":"G_UL4ZhOyX8n", "type":rootFolder.BOOKMARK, "title":"reddit: the front page of the internet 2", "uri":"http://www.reddit.com?1", index:1},
-    ];
+    let items = [{
+      "id": "G_UL4ZhOyX8m",
+      "type": rootFolder.BOOKMARK,
+      "title": "reddit: the front page of the internet 1",
+      "uri": "http://www.reddit.com",
+      index: 2
+    }, {
+      "id": "G_UL4ZhOyX8n",
+      "type": rootFolder.BOOKMARK,
+      "title": "reddit: the front page of the internet 2",
+      "uri": "http://www.reddit.com?1",
+      index: 1
+    }];
     yield rootFolder.mergeRemoteItems(items);
 
     let localItems = yield rootFolder.getLocalItems();
     equal(Object.keys(localItems).length, items.length, "found merged items");
   } finally {
     yield CloudSync().bookmarks.deleteRootFolder("TEST");
   }
 });
 
 add_task(function* test_merge_bookmarks_in_folders() {
   try {
     let rootFolder = yield CloudSync().bookmarks.getRootFolder("TEST");
     ok(rootFolder.id, "root folder id is ok");
 
-    let items = [
-      {"id":"G_UL4ZhOyX8m", "type":rootFolder.BOOKMARK, "title":"reddit: the front page of the internet 1", "uri":"http://www.reddit.com", index:2},
-      {"id":"G_UL4ZhOyX8n", "type":rootFolder.BOOKMARK, parent:"G_UL4ZhOyX8x", "title":"reddit: the front page of the internet 2", "uri":"http://www.reddit.com/?a=å%20ä%20ö", index:1},
-      {"id":"G_UL4ZhOyX8x", "type":rootFolder.FOLDER},
-    ];
+    let items = [{
+      "id": "G_UL4ZhOyX8m",
+      "type": rootFolder.BOOKMARK,
+      "title": "reddit: the front page of the internet 1",
+      "uri": "http://www.reddit.com",
+      index: 2
+    }, {
+      "id": "G_UL4ZhOyX8n",
+      "type": rootFolder.BOOKMARK,
+      parent: "G_UL4ZhOyX8x",
+      "title": "reddit: the front page of the internet 2",
+      "uri": "http://www.reddit.com/?a=å%20ä%20ö",
+      index: 1
+    }, {
+      "id": "G_UL4ZhOyX8x",
+      "type": rootFolder.FOLDER
+    }];
     yield rootFolder.mergeRemoteItems(items);
 
     let localItems = yield rootFolder.getLocalItems();
     equal(localItems.length, items.length, "found merged items");
 
     localItems.forEach(function(item) {
       ok(item.id == "G_UL4ZhOyX8m" ||
          item.id == "G_UL4ZhOyX8n" ||
--- a/services/cloudsync/tests/xpcshell/test_tabs.js
+++ b/services/cloudsync/tests/xpcshell/test_tabs.js
@@ -12,18 +12,25 @@ function run_test() {
 add_task(function* test_get_remote_tabs() {
   let cloudSync = CloudSync();
   let clients = yield cloudSync.tabs.getRemoteTabs();
   equal(clients.length, 0);
 
   yield cloudSync.tabs.mergeRemoteTabs({
       id: "001",
       name: "FakeClient",
-    }, [
-      {url:"https://www.google.ca?a=å%20ä%20ö", title:"Google Canada", icon:"https://www.google.ca/favicon.ico", lastUsed:0},
-      {url:"http://www.reddit.com", title:"Reddit", icon:"http://www.reddit.com/favicon.ico", lastUsed:1},
-    ]);
+    }, [{
+      url: "https://www.google.ca?a=å%20ä%20ö",
+      title: "Google Canada",
+      icon: "https://www.google.ca/favicon.ico",
+      lastUsed: 0
+    }, {
+      url: "http://www.reddit.com",
+      title: "Reddit",
+      icon: "http://www.reddit.com/favicon.ico",
+      lastUsed: 1
+    }]);
   ok(cloudSync.tabs.hasRemoteTabs());
 
   clients = yield cloudSync.tabs.getRemoteTabs();
   equal(clients.length, 1);
   equal(clients[0].tabs.size, 2);
 });
--- a/services/common/tests/unit/test_blocklist_certificates.js
+++ b/services/common/tests/unit/test_blocklist_certificates.js
@@ -164,89 +164,98 @@ function getSampleResponse(req, port) {
     "GET:/v1/?": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress"
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
+      "responseBody": JSON.stringify({
+        "settings": {
+          "batch_max_requests": 25
+        },
+        "url": `http://localhost:${port}/v1/`,
+        "documentation": "https://kinto.readthedocs.org/",
+        "version": "1.5.1",
+        "commit": "cbc6f58",
+        "hello": "kinto"
+      })
     },
     "GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"1000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{}]})
+      "responseBody": JSON.stringify({"data": [{}]})
     },
     "GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified&_since=1000": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"3000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "issuerName": "MEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHjAcBgNVBAMTFXRoYXd0ZSBFViBTU0wgQ0EgLSBHMw==",
-        "serialNumber":"CrTHPEE6AZSfI3jysin2bA==",
-        "id":"78cf8900-fdea-4ce5-f8fb-b78710617718",
-        "last_modified":3000
+        "serialNumber": "CrTHPEE6AZSfI3jysin2bA==",
+        "id": "78cf8900-fdea-4ce5-f8fb-b78710617718",
+        "last_modified": 3000
       }]})
     },
     "GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified&_since=3000": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"4000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
-        "issuerName":"MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ",
-        "serialNumber":"ATFpsA==",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02c",
-        "last_modified":4000
+      "responseBody": JSON.stringify({"data": [{
+        "issuerName": "MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ",
+        "serialNumber": "ATFpsA==",
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02c",
+        "last_modified": 4000
       }, {
-        "subject":"MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5",
-        "pubKeyHash":"VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02d",
-        "last_modified":4000
+        "subject": "MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5",
+        "pubKeyHash": "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=",
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02d",
+        "last_modified": 4000
       }]})
     },
     "GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified&_since=4000": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"5000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
-        "issuerName":"not a base64 encoded issuer",
-        "serialNumber":"not a base64 encoded serial",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02e",
-        "last_modified":5000
+      "responseBody": JSON.stringify({"data": [{
+        "issuerName": "not a base64 encoded issuer",
+        "serialNumber": "not a base64 encoded serial",
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02e",
+        "last_modified": 5000
       }, {
-        "subject":"not a base64 encoded subject",
-        "pubKeyHash":"not a base64 encoded pubKeyHash",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02f",
-        "last_modified":5000
+        "subject": "not a base64 encoded subject",
+        "pubKeyHash": "not a base64 encoded pubKeyHash",
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02f",
+        "last_modified": 5000
       }, {
-        "subject":"MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5",
-        "pubKeyHash":"VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02g",
-        "last_modified":5000
+        "subject": "MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5",
+        "pubKeyHash": "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=",
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02g",
+        "last_modified": 5000
       }]})
     }
   };
   return responses[`${req.method}:${req.path}?${req.queryString}`] ||
          responses[req.method];
 
 }
--- a/services/common/tests/unit/test_blocklist_clients.js
+++ b/services/common/tests/unit/test_blocklist_clients.js
@@ -226,28 +226,37 @@ function getSampleResponse(req, port) {
     "GET:/v1/?": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress"
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
+      "responseBody": JSON.stringify({
+        "settings": {
+          "batch_max_requests": 25
+        },
+        "url": `http://localhost:${port}/v1/`,
+        "documentation": "https://kinto.readthedocs.org/",
+        "version": "1.5.1",
+        "commit": "cbc6f58",
+        "hello": "kinto"
+      })
     },
     "GET:/v1/buckets/blocklists/collections/addons/records?_sort=-last_modified": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"3000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "prefs": [],
         "blockID": "i539",
         "last_modified": 3000,
         "versionRange": [{
           "targetApplication": [],
           "maxVersion": "*",
           "minVersion": "0",
           "severity": "1"
@@ -260,34 +269,34 @@ function getSampleResponse(req, port) {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"3000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "matchFilename": "NPFFAddOn.dll",
         "blockID": "p28",
         "id": "7b1e0b3c-e390-a817-11b6-a6887f65f56e",
         "last_modified": 3000,
         "versionRange": []
       }]})
     },
     "GET:/v1/buckets/blocklists/collections/gfx/records?_sort=-last_modified": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"3000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "driverVersionComparator": "LESS_THAN_OR_EQUAL",
         "driverVersion": "8.17.12.5896",
         "vendor": "0x10de",
         "blockID": "g36",
         "feature": "DIRECT3D_9_LAYERS",
         "devices": ["0x0a6c"],
         "featureStatus": "BLOCKED_DRIVER_VERSION",
         "last_modified": 3000,
@@ -299,17 +308,17 @@ function getSampleResponse(req, port) {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"4000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "prefs": [],
         "blockID": "i808",
         "last_modified": 4000,
         "versionRange": [{
           "targetApplication": [],
           "maxVersion": "*",
           "minVersion": "0",
           "severity": "3"
@@ -334,17 +343,17 @@ function getSampleResponse(req, port) {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"4000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "infoURL": "https://get.adobe.com/flashplayer/",
         "blockID": "p1044",
         "matchFilename": "libflashplayer\\.so",
         "last_modified": 4000,
         "versionRange": [{
           "targetApplication": [],
           "minVersion": "11.2.202.509",
           "maxVersion": "11.2.202.539",
@@ -371,17 +380,17 @@ function getSampleResponse(req, port) {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"4000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "vendor": "0x8086",
         "blockID": "g204",
         "feature": "WEBGL_MSAA",
         "devices": [],
         "id": "c96bca82-e6bd-044d-14c4-9c1d67e9283a",
         "last_modified": 4000,
         "os": "Darwin 10",
         "featureStatus": "BLOCKED_DEVICE"
--- a/services/common/tests/unit/test_blocklist_pinning.js
+++ b/services/common/tests/unit/test_blocklist_pinning.js
@@ -213,127 +213,136 @@ function getSampleResponse(req, port) {
     "GET:/v1/?": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress"
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
+      "responseBody": JSON.stringify({
+        "settings": {
+          "batch_max_requests": 25
+        },
+        "url": `http://localhost:${port}/v1/`,
+        "documentation": "https://kinto.readthedocs.org/",
+        "version": "1.5.1",
+        "commit": "cbc6f58",
+        "hello": "kinto"
+      })
     },
     "GET:/v1/buckets/pinning/collections/pins/records?_sort=-last_modified": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"3000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "pinType": "KeyPin",
         "hostName": "one.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "pins" : ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
+        "pins": ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
                   "M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="],
-        "versions" : [appInfo.version],
-        "id":"78cf8900-fdea-4ce5-f8fb-b78710617718",
-        "last_modified":3000
+        "versions": [appInfo.version],
+        "id": "78cf8900-fdea-4ce5-f8fb-b78710617718",
+        "last_modified": 3000
       }]})
     },
     "GET:/v1/buckets/pinning/collections/pins/records?_sort=-last_modified&_since=3000": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"4000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
+      "responseBody": JSON.stringify({"data": [{
         "pinType": "KeyPin",
         "hostName": "two.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "pins" : ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
+        "pins": ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
                   "M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="],
-        "versions" : [appInfo.version],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02c",
-        "last_modified":4000
+        "versions": [appInfo.version],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02c",
+        "last_modified": 4000
       }, {
         "pinType": "KeyPin",
         "hostName": "three.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "pins" : ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
+        "pins": ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
                   "M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="],
-        "versions" : [appInfo.version, "some other version that won't match"],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02d",
-        "last_modified":4000
+        "versions": [appInfo.version, "some other version that won't match"],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02d",
+        "last_modified": 4000
       }, {
         "pinType": "KeyPin",
         "hostName": "four.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "pins" : ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
+        "pins": ["cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
                   "M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="],
-        "versions" : ["some version that won't match"],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02e",
-        "last_modified":4000
+        "versions": ["some version that won't match"],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02e",
+        "last_modified": 4000
       }, {
         "pinType": "STSPin",
         "hostName": "five.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "versions" : [appInfo.version, "some version that won't match"],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc032",
-        "last_modified":4000
+        "versions": [appInfo.version, "some version that won't match"],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc032",
+        "last_modified": 4000
       }]})
     },
     "GET:/v1/buckets/pinning/collections/pins/records?_sort=-last_modified&_since=4000": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"5000\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{
-        "irrelevant":"this entry looks nothing whatsoever like a pin preload",
+      "responseBody": JSON.stringify({"data": [{
+        "irrelevant": "this entry looks nothing whatsoever like a pin preload",
         "pinType": "KeyPin",
-        "id":"dabafde9-df4a-ddba-2548-748da04cc02f",
-        "last_modified":5000
+        "id": "dabafde9-df4a-ddba-2548-748da04cc02f",
+        "last_modified": 5000
       }, {
-        "irrelevant":"this entry has data of the wrong type",
+        "irrelevant": "this entry has data of the wrong type",
         "pinType": "KeyPin",
         "hostName": 3,
         "includeSubdomains": "nonsense",
         "expires": "more nonsense",
-        "pins" : [1, 2, 3, 4],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc030",
-        "last_modified":5000
+        "pins": [1, 2, 3, 4],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc030",
+        "last_modified": 5000
       }, {
-        "irrelevant":"this entry is missing the actual pins",
+        "irrelevant": "this entry is missing the actual pins",
         "pinType": "KeyPin",
         "hostName": "missingpins.example.com",
         "includeSubdomains": false,
         "expires": new Date().getTime() + 1000000,
-        "versions" : [appInfo.version],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc031",
-        "last_modified":5000
+        "versions": [appInfo.version],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc031",
+        "last_modified": 5000
       }, {
         "pinType": "STSPin",
         "hostName": "five.example.com",
         "includeSubdomains": true,
         "expires": new Date().getTime() + 1000000,
-        "versions" : [appInfo.version, "some version that won't match"],
-        "id":"dabafde9-df4a-ddba-2548-748da04cc032",
-        "last_modified":5000
+        "versions": [appInfo.version, "some version that won't match"],
+        "id": "dabafde9-df4a-ddba-2548-748da04cc032",
+        "last_modified": 5000
       }]})
     }
   };
   return responses[`${req.method}:${req.path}?${req.queryString}`] ||
          responses[req.method];
 
 }
--- a/services/common/tests/unit/test_blocklist_signatures.js
+++ b/services/common/tests/unit/test_blocklist_signatures.js
@@ -250,17 +250,26 @@ add_task(function* test_check_signatures
     comment: "RESPONSE_SERVER_SETTINGS",
     sampleHeaders: [
       "Access-Control-Allow-Origin: *",
       "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
       "Content-Type: application/json; charset=UTF-8",
       "Server: waitress"
     ],
     status: {status: 200, statusText: "OK"},
-    responseBody: JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
+    responseBody: JSON.stringify({
+      "settings": {
+        "batch_max_requests": 25
+      },
+      "url": `http://localhost:${port}/v1/`,
+      "documentation": "https://kinto.readthedocs.org/",
+      "version": "1.5.1",
+      "commit": "cbc6f58",
+      "hello": "kinto"
+    })
   };
 
   // This is the initial, empty state of the collection. This is only used
   // for the first sync.
   const RESPONSE_EMPTY_INITIAL = {
     comment: "RESPONSE_EMPTY_INITIAL",
     sampleHeaders: [
       "Content-Type: application/json; charset=UTF-8",
@@ -276,17 +285,17 @@ add_task(function* test_check_signatures
   // The collection metadata containing the signature for the empty
   // collection.
   const RESPONSE_META_EMPTY_SIG =
     makeMetaResponse(1000, RESPONSE_BODY_META_EMPTY_SIG,
                      "RESPONSE_META_EMPTY_SIG");
 
   // Here, we map request method and path to the available responses
   const emptyCollectionResponses = {
-    "GET:/test_blocklist_signatures/test_cert_chain.pem?":[RESPONSE_CERT_CHAIN],
+    "GET:/test_blocklist_signatures/test_cert_chain.pem?": [RESPONSE_CERT_CHAIN],
     "GET:/v1/?": [RESPONSE_SERVER_SETTINGS],
     "GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified":
       [RESPONSE_EMPTY_INITIAL],
     "GET:/v1/buckets/blocklists/collections/certificates?":
       [RESPONSE_META_EMPTY_SIG]
   };
 
   // .. and use this map to register handlers for each path
--- a/services/common/tests/unit/test_kinto.js
+++ b/services/common/tests/unit/test_kinto.js
@@ -14,17 +14,17 @@ var server;
 const kintoFilename = "kinto.sqlite";
 
 function do_get_kinto_sqliteHandle() {
   return FirefoxAdapter.openConnection({path: kintoFilename});
 }
 
 function do_get_kinto_collection(sqliteHandle, collection = "test_collection") {
   let config = {
-    remote:`http://localhost:${server.identity.primaryPort}/v1/`,
+    remote: `http://localhost:${server.identity.primaryPort}/v1/`,
     headers: {Authorization: "Basic " + btoa("user:pass")},
     adapter: FirefoxAdapter,
     adapterOptions: {sqliteHandle},
   };
   return new Kinto(config).collection(collection);
 }
 
 function* clear_collection() {
@@ -373,48 +373,78 @@ function getSampleResponse(req, port) {
     "GET:/v1/?": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress"
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
+      "responseBody": JSON.stringify({
+        "settings": {
+          "batch_max_requests": 25
+        },
+        "url": `http://localhost:${port}/v1/`,
+        "documentation": "https://kinto.readthedocs.org/",
+        "version": "1.5.1",
+        "commit": "cbc6f58",
+        "hello": "kinto"
+      })
     },
     "GET:/v1/buckets/default/collections/test_collection/records?_sort=-last_modified": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"1445606341071\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{"last_modified":1445606341071, "done":false, "id":"68db8313-686e-4fff-835e-07d78ad6f2af", "title":"New test"}]})
+      "responseBody": JSON.stringify({
+        "data": [{
+          "last_modified": 1445606341071,
+          "done": false,
+          "id": "68db8313-686e-4fff-835e-07d78ad6f2af",
+          "title": "New test"
+        }]
+      })
     },
     "GET:/v1/buckets/default/collections/test_collection/records?_sort=-last_modified&_since=1445606341071": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"1445607941223\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{"last_modified":1445607941223, "done":false, "id":"901967b0-f729-4b30-8d8d-499cba7f4b1d", "title":"Another new test"}]})
+      "responseBody": JSON.stringify({
+        "data": [{
+          "last_modified": 1445607941223,
+          "done": false,
+          "id": "901967b0-f729-4b30-8d8d-499cba7f4b1d",
+          "title": "Another new test"
+        }]
+      })
     },
     "GET:/v1/buckets/default/collections/test_collection/records?_sort=-last_modified&_since=1445607941223": {
       "sampleHeaders": [
         "Access-Control-Allow-Origin: *",
         "Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
         "Content-Type: application/json; charset=UTF-8",
         "Server: waitress",
         "Etag: \"1445607541265\""
       ],
       "status": {status: 200, statusText: "OK"},
-      "responseBody": JSON.stringify({"data":[{"last_modified":1445607541265, "done":false, "id":"901967b0-f729-4b30-8d8d-499cba7f4b1d", "title":"Modified title"}]})
+      "responseBody": JSON.stringify({
+        "data": [{
+          "last_modified": 1445607541265,
+          "done": false,
+          "id": "901967b0-f729-4b30-8d8d-499cba7f4b1d",
+          "title": "Modified title"
+        }]
+      })
     }
   };
   return responses[`${req.method}:${req.path}?${req.queryString}`] ||
          responses[req.method];
 
 }
--- a/services/common/tests/unit/test_storage_adapter.js
+++ b/services/common/tests/unit/test_storage_adapter.js
@@ -38,30 +38,30 @@ function test_collection_operations() {
     yield adapter.clear();
     yield sqliteHandle.close();
   });
 
   // test creating new records... and getting them again
   add_task(function* test_kinto_create_new_get_existing() {
     let sqliteHandle = yield do_get_kinto_connection();
     let adapter = do_get_kinto_adapter(sqliteHandle);
-    let record = {id:"test-id", foo:"bar"};
+    let record = {id: "test-id", foo: "bar"};
     yield adapter.execute((transaction) => transaction.create(record));
     let newRecord = yield adapter.get("test-id");
     // ensure the record is the same as when it was added
     deepEqual(record, newRecord);
     yield sqliteHandle.close();
   });
 
   // test removing records
   add_task(function* test_kinto_can_remove_some_records() {
     let sqliteHandle = yield do_get_kinto_connection();
     let adapter = do_get_kinto_adapter(sqliteHandle);
     // create a second record
-    let record = {id:"test-id-2", foo:"baz"};
+    let record = {id: "test-id-2", foo: "baz"};
     yield adapter.execute((transaction) => transaction.create(record));
     let newRecord = yield adapter.get("test-id-2");
     deepEqual(record, newRecord);
     // delete the record
     yield adapter.execute((transaction) => transaction.delete(record.id));
     newRecord = yield adapter.get(record.id);
     // ... and ensure it's no longer there
     do_check_eq(newRecord, undefined);
@@ -81,33 +81,33 @@ function test_collection_operations() {
     do_check_eq(newRecord, undefined);
     yield sqliteHandle.close();
   });
 
   // test updating records... and getting them again
   add_task(function* test_kinto_update_get_existing() {
     let sqliteHandle = yield do_get_kinto_connection();
     let adapter = do_get_kinto_adapter(sqliteHandle);
-    let originalRecord = {id:"test-id", foo:"bar"};
-    let updatedRecord = {id:"test-id", foo:"baz"};
+    let originalRecord = {id: "test-id", foo: "bar"};
+    let updatedRecord = {id: "test-id", foo: "baz"};
     yield adapter.clear();
     yield adapter.execute((transaction) => transaction.create(originalRecord));
     yield adapter.execute((transaction) => transaction.update(updatedRecord));
     // ensure the record exists
     let newRecord = yield adapter.get("test-id");
     // ensure the record is the same as when it was added
     deepEqual(updatedRecord, newRecord);
     yield sqliteHandle.close();
   });
 
   // test listing records
   add_task(function* test_kinto_list() {
     let sqliteHandle = yield do_get_kinto_connection();
     let adapter = do_get_kinto_adapter(sqliteHandle);
-    let originalRecord = {id:"test-id-1", foo:"bar"};
+    let originalRecord = {id: "test-id-1", foo: "bar"};
     let records = yield adapter.list();
     do_check_eq(records.length, 1);
     yield adapter.execute((transaction) => transaction.create(originalRecord));
     records = yield adapter.list();
     do_check_eq(records.length, 2);
     yield sqliteHandle.close();
   });
 
--- a/services/crypto/modules/WeaveCrypto.js
+++ b/services/crypto/modules/WeaveCrypto.js
@@ -23,24 +23,24 @@ const KEY_DERIVATION_HASHING_ALGO = "SHA
 const KEY_DERIVATION_ITERATIONS   = 4096; // PKCS#5 recommends at least 1000.
 const DERIVED_KEY_ALGO            = CRYPT_ALGO;
 
 this.WeaveCrypto = function WeaveCrypto() {
     this.init();
 };
 
 WeaveCrypto.prototype = {
-    prefBranch : null,
-    debug      : true,  // services.sync.log.cryptoDebug
+    prefBranch: null,
+    debug: true,  // services.sync.log.cryptoDebug
 
-    observer : {
-        _self : null,
+    observer: {
+        _self: null,
 
-        QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
-                                                Ci.nsISupportsWeakReference]),
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                               Ci.nsISupportsWeakReference]),
 
         observe(subject, topic, data) {
             let self = this._self;
             self.log("Observed " + topic + " topic.");
             if (topic == "nsPref:changed") {
                 self.debug = self.prefBranch.getBoolPref("cryptoDebug");
             }
         }
--- a/services/crypto/modules/utils.js
+++ b/services/crypto/modules/utils.js
@@ -177,17 +177,17 @@ this.CryptoUtils = {
    * hmacLen: The hmac length
    *
    * The default value of 20 for hmacLen is appropriate for SHA1.  For SHA256,
    * hmacLen should be 32.
    *
    * The output is an octet string of length dkLen, which you
    * can encode as you wish.
    */
-  pbkdf2Generate : function pbkdf2Generate(P, S, c, dkLen,
+  pbkdf2Generate: function pbkdf2Generate(P, S, c, dkLen,
                        hmacAlg = Ci.nsICryptoHMAC.SHA1, hmacLen = 20) {
 
     // We don't have a default in the algo itself, as NSS does.
     if (!dkLen) {
       throw new Error("dkLen should be defined");
     }
 
     function F(S, c, i, h) {
--- a/services/sync/modules/engines/clients.js
+++ b/services/sync/modules/engines/clients.js
@@ -291,25 +291,25 @@ ClientEngine.prototype = {
     const allCommands = this._readCommands();
     delete allCommands[clientId];
     this._saveCommands(allCommands);
   },
 
   // We assume that clients not present in the FxA Device Manager list have been
   // disconnected and so are stale
   _refreshKnownStaleClients() {
-    this._log.debug('Refreshing the known stale clients list');
+    this._log.debug("Refreshing the known stale clients list");
     let localClients = Object.values(this._store._remoteClients)
                              .filter(client => client.fxaDeviceId) // iOS client records don't have fxaDeviceId
                              .map(client => client.fxaDeviceId);
     let fxaClients;
     try {
       fxaClients = Async.promiseSpinningly(this.fxAccounts.getDeviceList()).map(device => device.id);
     } catch (ex) {
-      this._log.error('Could not retrieve the FxA device list', ex);
+      this._log.error("Could not retrieve the FxA device list", ex);
       this._knownStaleFxADeviceIds = [];
       return;
     }
     this._knownStaleFxADeviceIds = Utils.arraySub(localClients, fxaClients);
   },
 
   _syncStartup() {
     // Reupload new client record periodically.
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -297,38 +297,38 @@ this.Utils = {
   base64Key: function base64Key(keyData) {
     return btoa(keyData);
   },
 
   /**
    * N.B., salt should be base64 encoded, even though we have to decode
    * it later!
    */
-  derivePresentableKeyFromPassphrase : function derivePresentableKeyFromPassphrase(passphrase, salt, keyLength, forceJS) {
+  derivePresentableKeyFromPassphrase: function derivePresentableKeyFromPassphrase(passphrase, salt, keyLength, forceJS) {
     let k = CryptoUtils.deriveKeyFromPassphrase(passphrase, salt, keyLength,
                                                 forceJS);
     return Utils.encodeKeyBase32(k);
   },
 
   /**
    * N.B., salt should be base64 encoded, even though we have to decode
    * it later!
    */
-  deriveEncodedKeyFromPassphrase : function deriveEncodedKeyFromPassphrase(passphrase, salt, keyLength, forceJS) {
+  deriveEncodedKeyFromPassphrase: function deriveEncodedKeyFromPassphrase(passphrase, salt, keyLength, forceJS) {
     let k = CryptoUtils.deriveKeyFromPassphrase(passphrase, salt, keyLength,
                                                 forceJS);
     return Utils.base64Key(k);
   },
 
   /**
    * Take a base64-encoded 128-bit AES key, returning it as five groups of five
    * uppercase alphanumeric characters, separated by hyphens.
    * A.K.A. base64-to-base32 encoding.
    */
-  presentEncodedKeyAsSyncKey : function presentEncodedKeyAsSyncKey(encodedKey) {
+  presentEncodedKeyAsSyncKey: function presentEncodedKeyAsSyncKey(encodedKey) {
     return Utils.encodeKeyBase32(atob(encodedKey));
   },
 
   jsonFilePath(filePath) {
     return OS.Path.normalize(OS.Path.join(OS.Constants.Path.profileDir, "weave", filePath + ".json"));
   },
 
   /**
@@ -456,23 +456,23 @@ this.Utils = {
     }
     return OS.File.remove(path, { ignoreAbsent: true });
   },
 
   getErrorString: function Utils_getErrorString(error, args) {
     try {
       if (args) {
         return Str.errors.formatStringFromName(error, args, args.length);
-      } else {
-        return Str.errors.GetStringFromName(error);
       }
+      return Str.errors.GetStringFromName(error);
+
     } catch (e) {}
 
     // basically returns "Unknown Error"
-    return Str.errors.GetStringFromName('error.reason.unknown');
+    return Str.errors.GetStringFromName("error.reason.unknown");
   },
 
   /**
    * Generate 26 characters.
    */
   generatePassphrase: function generatePassphrase() {
     // Note that this is a different base32 alphabet to the one we use for
     // other tasks. It's lowercase, uses different letters, and needs to be
--- a/services/sync/tests/tps/test_existing_bookmarks.js
+++ b/services/sync/tests/tps/test_existing_bookmarks.js
@@ -53,32 +53,32 @@ var bookmarks_after = {
     }
   ]
 };
 
 /*
  * Test phases
  */
 
-Phase('phase1', [
+Phase("phase1", [
   [Bookmarks.add, bookmarks_initial],
   [Bookmarks.verify, bookmarks_initial],
   [Sync]
 ]);
 
-Phase('phase2', [
+Phase("phase2", [
   [Bookmarks.add, bookmarks_initial],
   [Bookmarks.verify, bookmarks_initial],
   [Sync]
 ]);
 
-Phase('phase3', [
+Phase("phase3", [
   [Bookmarks.verify, bookmarks_initial],
   [Bookmarks.modify, bookmarks_initial],
   [Bookmarks.verify, bookmarks_after],
   [Sync]
 ]);
 
-Phase('phase4', [
+Phase("phase4", [
   [Sync],
   [Bookmarks.verify, bookmarks_after]
 ]);
 
--- a/services/sync/tests/unit/test_bookmark_engine.js
+++ b/services/sync/tests/unit/test_bookmark_engine.js
@@ -508,32 +508,32 @@ function FakeRecord(constructor, r) {
 
 // Bug 632287.
 add_task(async function test_mismatched_types() {
   _("Ensure that handling a record that changes type causes deletion " +
     "then re-adding.");
 
   let oldRecord = {
     "id": "l1nZZXfB8nC7",
-    "type":"folder",
-    "parentName":"Bookmarks Toolbar",
-    "title":"Innerst i Sneglehode",
-    "description":null,
+    "type": "folder",
+    "parentName": "Bookmarks Toolbar",
+    "title": "Innerst i Sneglehode",
+    "description": null,
     "parentid": "toolbar"
   };
   oldRecord.cleartext = oldRecord;
 
   let newRecord = {
     "id": "l1nZZXfB8nC7",
-    "type":"livemark",
-    "siteUri":"http://sneglehode.wordpress.com/",
-    "feedUri":"http://sneglehode.wordpress.com/feed/",
-    "parentName":"Bookmarks Toolbar",
-    "title":"Innerst i Sneglehode",
-    "description":null,
+    "type": "livemark",
+    "siteUri": "http://sneglehode.wordpress.com/",
+    "feedUri": "http://sneglehode.wordpress.com/feed/",
+    "parentName": "Bookmarks Toolbar",
+    "title": "Innerst i Sneglehode",
+    "description": null,
     "children":
       ["HCRq40Rnxhrd", "YeyWCV1RVsYw", "GCceVZMhvMbP", "sYi2hevdArlF",
        "vjbZlPlSyGY8", "UtjUhVyrpeG6", "rVq8WMG2wfZI", "Lx0tcy43ZKhZ",
        "oT74WwV8_j4P", "IztsItWVSo3-"],
     "parentid": "toolbar"
   };
   newRecord.cleartext = newRecord;
 
--- a/services/sync/tests/unit/test_bookmark_livemarks.js
+++ b/services/sync/tests/unit/test_bookmark_livemarks.js
@@ -16,24 +16,24 @@ var engine = Service.engineManager.get("
 var store = engine._store;
 
 // Record borrowed from Bug 631361.
 var record631361 = {
   id: "M5bwUKK8hPyF",
   index: 150,
   modified: 1296768176.49,
   payload:
-  {"id":"M5bwUKK8hPyF",
-   "type":"livemark",
-   "siteUri":"http://www.bbc.co.uk/go/rss/int/news/-/news/",
-   "feedUri":"http://fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
-   "parentName":"Bookmarks Toolbar",
-   "parentid":"toolbar",
-   "title":"Latest Headlines",
-   "description":"",
+  {"id": "M5bwUKK8hPyF",
+   "type": "livemark",
+   "siteUri": "http://www.bbc.co.uk/go/rss/int/news/-/news/",
+   "feedUri": "http://fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
+   "parentName": "Bookmarks Toolbar",
+   "parentid": "toolbar",
+   "title": "Latest Headlines",
+   "description": "",
    "children":
      ["7oBdEZB-8BMO", "SUd1wktMNCTB", "eZe4QWzo1BcY", "YNBhGwhVnQsN",
       "92Aw2SMEkFg0", "uw0uKqrVFwd-", "x7mx2P3--8FJ", "d-jVF8UuC9Ye",
       "DV1XVtKLEiZ5", "g4mTaTjr837Z", "1Zi5W3lwBw8T", "FEYqlUHtbBWS",
       "qQd2u7LjosCB", "VUs2djqYfbvn", "KuhYnHocu7eg", "u2gcg9ILRg-3",
       "hfK_RP-EC7Ol", "Aq5qsa4E5msH", "6pZIbxuJTn-K", "k_fp0iN3yYMR",
       "59YD3iNOYO8O", "01afpSdAk2iz", "Cq-kjXDEPIoP", "HtNTjt9UwWWg",
       "IOU8QRSrTR--", "HJ5lSlBx6d1D", "j2dz5R5U6Khc", "5GvEjrNR0yJl",
--- a/services/sync/tests/unit/test_bookmark_repair.js
+++ b/services/sync/tests/unit/test_bookmark_repair.js
@@ -69,17 +69,17 @@ async function promiseValidationDone(exp
   let obs = promiseOneObserver("weave:engine:validate:finish");
   let { subject: validationResult } = await obs;
   // check the results - anything non-zero is checked against |expected|
   let summary = validationResult.problems.getSummary();
   let actual = summary.filter(({name, count}) => count);
   actual.sort((a, b) => String(a.name).localeCompare(b.name));
   expected.sort((a, b) => String(a.name).localeCompare(b.name));
   deepEqual(actual, expected);
-};
+}
 
 async function cleanup(server) {
   bookmarksEngine._store.wipe();
   clientsEngine._store.wipe();
   Svc.Prefs.resetBranch("");
   Service.recordManager.clearCache();
   await promiseStopServer(server);
 }
@@ -161,18 +161,18 @@ add_task(async function test_bookmark_re
       source: PlacesUtils.bookmarks.SOURCE_SYNC,
     });
     deepEqual(bookmarksEngine.pullNewChanges(), {},
       `Should not upload tombstone for ${bookmarkInfo.guid}`);
 
     // sync again - we should have a few problems...
     _("Sync again to trigger repair");
     validationPromise = promiseValidationDone([
-      {"name":"missingChildren","count":1},
-      {"name":"structuralDifferences","count":1},
+      {"name": "missingChildren", "count": 1},
+      {"name": "structuralDifferences", "count": 1},
     ]);
     Service.sync();
     await validationPromise;
     let flowID = Svc.Prefs.get("repairs.bookmarks.flowID");
     checkRecordedEvents([{
       object: "repair",
       method: "started",
       value: undefined,
@@ -391,18 +391,18 @@ add_task(async function test_repair_clie
     // sanity check we aren't going to sync this removal.
     do_check_empty(bookmarksEngine.pullNewChanges());
     // sanity check that the bookmark is not there anymore
     do_check_false(await PlacesUtils.bookmarks.fetch(bookmarkInfo.guid));
 
     // sync again - we should have a few problems...
     _("Syncing again.");
     validationPromise = promiseValidationDone([
-      {"name":"clientMissing","count":1},
-      {"name":"structuralDifferences","count":1},
+      {"name": "clientMissing", "count": 1},
+      {"name": "structuralDifferences", "count": 1},
     ]);
     Service.sync();
     await validationPromise;
 
     // We shouldn't have started a repair with our second client.
     equal(clientsEngine.getClientCommands(remoteID).length, 0);
 
     // Trigger a sync (will request the missing item)
@@ -475,18 +475,18 @@ add_task(async function test_repair_serv
     await validationPromise;
 
     // Now we will reach into the server and hard-delete the bookmark
     user.collection("bookmarks").wbo(bookmarkInfo.guid).delete();
 
     // sync again - we should have a few problems...
     _("Syncing again.");
     validationPromise = promiseValidationDone([
-      {"name":"serverMissing","count":1},
-      {"name":"missingChildren","count":1},
+      {"name": "serverMissing", "count": 1},
+      {"name": "missingChildren", "count": 1},
     ]);
     Service.sync();
     await validationPromise;
 
     // We shouldn't have started a repair with our second client.
     equal(clientsEngine.getClientCommands(remoteID).length, 0);
 
     // Trigger a sync (will upload the missing item)
@@ -562,19 +562,19 @@ add_task(async function test_repair_serv
     server.insertWBO("foo", "bookmarks", new ServerWBO(bookmarkInfo.guid, encryptPayload({
       id: bookmarkInfo.guid,
       deleted: true,
     }), Date.now() / 1000));
 
     // sync again - we should have a few problems...
     _("Syncing again.");
     validationPromise = promiseValidationDone([
-      {"name":"serverDeleted","count":1},
-      {"name":"deletedChildren","count":1},
-      {"name":"orphans","count":1}
+      {"name": "serverDeleted", "count": 1},
+      {"name": "deletedChildren", "count": 1},
+      {"name": "orphans", "count": 1}
     ]);
     Service.sync();
     await validationPromise;
 
     // We shouldn't have started a repair with our second client.
     equal(clientsEngine.getClientCommands(remoteID).length, 0);
 
     // Trigger a sync (will upload the missing item)
--- a/services/sync/tests/unit/test_bookmark_repair_requestor.js
+++ b/services/sync/tests/unit/test_bookmark_repair_requestor.js
@@ -491,24 +491,24 @@ add_task(async function test_requestor_a
   requestor.continueRepairs(response);
 
   // We should have aborted now
   checkRepairFinished();
   const expected = [
     { method: "started",
       object: "repair",
       value: undefined,
-      extra: { flowID: flowID, numIDs: "3" },
+      extra: { flowID, numIDs: "3" },
     },
     { method: "request",
       object: "repair",
       value: "upload",
-      extra: { flowID: flowID, numIDs: "3", deviceID: "client-a" },
+      extra: { flowID, numIDs: "3", deviceID: "client-a" },
     },
     { method: "aborted",
       object: "repair",
       value: undefined,
-      extra: { flowID: flowID, numIDs: "3", reason: "other clients repairing" },
+      extra: { flowID, numIDs: "3", reason: "other clients repairing" },
     }
   ];
 
   deepEqual(mockService._recordedEvents, expected);
 });
--- a/services/sync/tests/unit/test_errorhandler_2.js
+++ b/services/sync/tests/unit/test_errorhandler_2.js
@@ -942,17 +942,17 @@ add_task(async function test_engine_appl
   enableValidationPrefs();
 
   let server = EHTestsCommon.sync_httpd_setup();
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   delete engine.exception;
   engine.sync = function sync() {
-    Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
+    Svc.Obs.notify("weave:engine:sync:applied", {newFailed: 1}, "catapult");
   };
 
   Svc.Prefs.set("log.appender.file.logOnError", true);
 
   let promiseObserved = promiseOneObserver("weave:service:reset-file-log");
 
   do_check_eq(Status.engines["catapult"], undefined);
   do_check_true(await EHTestsCommon.setUp(server));
--- a/services/sync/tps/extensions/tps/components/tps-cmdline.js
+++ b/services/sync/tps/extensions/tps/components/tps-cmdline.js
@@ -20,33 +20,33 @@ const nsISupportsString              = C
 const nsIWindowWatcher               = Components.interfaces.nsIWindowWatcher;
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function TPSCmdLineHandler() {}
 
 TPSCmdLineHandler.prototype = {
   classDescription: "TPSCmdLineHandler",
-  classID         : TPS_CMDLINE_CLSID,
-  contractID      : TPS_CMDLINE_CONTRACTID,
+  classID: TPS_CMDLINE_CLSID,
+  contractID: TPS_CMDLINE_CONTRACTID,
 
   QueryInterface: XPCOMUtils.generateQI([nsISupports,
                                          nsICommandLineHandler,
                                          nsICmdLineHandler]),   /* nsISupports */
 
   /* nsICmdLineHandler */
-  commandLineArgument : "-tps",
-  prefNameForStartup : "general.startup.tps",
-  helpText : "Run TPS tests with the given test file.",
-  handlesArgs : true,
-  defaultArgs : "",
-  openWindowWithArgs : true,
+  commandLineArgument: "-tps",
+  prefNameForStartup: "general.startup.tps",
+  helpText: "Run TPS tests with the given test file.",
+  handlesArgs: true,
+  defaultArgs: "",
+  openWindowWithArgs: true,
 
   /* nsICommandLineHandler */
-  handle : function handler_handle(cmdLine) {
+  handle: function handler_handle(cmdLine) {
     let options = {};
 
     let uristr = cmdLine.handleFlagWithParam("tps", false);
     if (uristr == null)
         return;
     let phase = cmdLine.handleFlagWithParam("tpsphase", false);
     if (phase == null)
         throw Error("must specify --tpsphase with --tps");
@@ -67,20 +67,20 @@ TPSCmdLineHandler.prototype = {
     Components.utils.import("resource://tps/tps.jsm");
     Components.utils.import("resource://tps/quit.js", TPS);
     let uri = cmdLine.resolveURI(uristr).spec;
     TPS.RunTestPhase(uri, phase, logfile, options);
 
     // cmdLine.preventDefault = true;
   },
 
-  helpInfo : "  --tps <file>              Run TPS tests with the given test file.\n" +
-             "  --tpsphase <phase>        Run the specified phase in the TPS test.\n" +
-             "  --tpslogfile <file>       Logfile for TPS output.\n" +
-             "  --ignore-unused-engines   Don't load engines not used in tests.\n",
+  helpInfo: "  --tps <file>              Run TPS tests with the given test file.\n" +
+            "  --tpsphase <phase>        Run the specified phase in the TPS test.\n" +
+            "  --tpslogfile <file>       Logfile for TPS output.\n" +
+            "  --ignore-unused-engines   Don't load engines not used in tests.\n",
 };
 
 
 var TPSCmdLineFactory = {
   createInstance(outer, iid) {
     if (outer != null) {
       throw new Error(Components.results.NS_ERROR_NO_AGGREGATION);
     }
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -276,32 +276,32 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "canvas"
 version = "0.0.1"
 dependencies = [
  "azure 0.15.0 (git+https://github.com/servo/rust-azure)",
  "canvas_traits 0.0.1",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "webrender_traits 0.35.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.35.0 (git+https://github.com/servo/webrender)",
 ]
@@ -506,32 +506,32 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.12.1"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -932,17 +932,17 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
  "style_traits 0.0.1",
  "stylo_tests 0.0.1",
@@ -1354,17 +1354,17 @@ source = "registry+https://github.com/ru
 [[package]]
 name = "layout"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx 0.0.1",
  "gfx_traits 0.0.1",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1661,17 +1661,17 @@ dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "msg"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.35.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
@@ -2239,17 +2239,17 @@ dependencies = [
  "base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
  "caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "deny_public_fields 0.0.1",
  "devtools_traits 0.0.1",
  "dom_struct 0.0.1",
  "domobject_derive 0.0.1",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
@@ -2309,17 +2309,17 @@ dependencies = [
 
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2380,17 +2380,17 @@ dependencies = [
  "webvr_traits 0.0.1",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.18.0"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
@@ -2730,17 +2730,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2769,17 +2769,17 @@ dependencies = [
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_tests"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "servo_atoms 0.0.1",
  "servo_config 0.0.1",
@@ -2788,30 +2788,30 @@ dependencies = [
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
@@ -3354,18 +3354,18 @@ dependencies = [
 "checksum cocoa 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a5d0bcb4d345adf9b4ada6c5bb3e2b87c8150b79c46f3f26446de5f4d48de4b"
 "checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
 "checksum compiletest_rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f344389765ad7bec166f64c1b39ed6dd2b54d81c4c5dd8af789169351d380c"
 "checksum cookie 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce776927cd64cbe74ebd1d9b375edb9d1b6bfa808618ddf9548645e019ebdfbb"
 "checksum core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f51ce3b8ebe311c56de14231eb57572c15abebd2d32b3bcb99bcdb9c101f5ac3"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
 "checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
-"checksum cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35e3e110221f306501253d8d34857040de365ce2d92ac0abb2f06dedc845d9d0"
-"checksum cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f0415de0bdbce823c0db204e00a62c8240fa2d3e04cd13ff7c6396e4446b95"
+"checksum cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b39404c5e04492194e3c69f1a10964b980f2c95c884a940f7903446779f6b027"
+"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum dbus 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47f881971824401c27bc1ff9f641d54ac66e0f409631806fa7be8cad8e6be450"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebb02aaf4b775afc96684b8402510a338086974e38570a1f65bea8c202eb77a7"
 "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
 "checksum device 0.0.1 (git+https://github.com/servo/devices)" = "<none>"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07c4c7cc7b396419bc0a4d90371d0cee16cb5053b53647d287c0b728000c41fe"
--- a/servo/components/canvas/Cargo.toml
+++ b/servo/components/canvas/Cargo.toml
@@ -7,17 +7,17 @@ publish = false
 
 [lib]
 name = "canvas"
 path = "lib.rs"
 
 [dependencies]
 azure = {git = "https://github.com/servo/rust-azure"}
 canvas_traits = {path = "../canvas_traits"}
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 gleam = "0.4"
 ipc-channel = "0.7"
 log = "0.3.5"
 num-traits = "0.1.32"
 offscreen_gl_context = "0.8"
 servo_config = {path = "../config"}
 webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas_traits/Cargo.toml
+++ b/servo/components/canvas_traits/Cargo.toml
@@ -5,16 +5,16 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "canvas_traits"
 path = "lib.rs"
 
 [dependencies]
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 heapsize = "0.3.0"
 heapsize_derive = "0.1"
 ipc-channel = "0.7"
 serde = {version = "0.9", features = ["unstable"]}
 serde_derive = "0.9"
 webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/layout/Cargo.toml
+++ b/servo/components/layout/Cargo.toml
@@ -9,17 +9,17 @@ publish = false
 name = "layout"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4"
 atomic_refcell = "0.1"
 bitflags = "0.7"
 canvas_traits = {path = "../canvas_traits"}
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 fnv = "1.0"
 gfx = {path = "../gfx"}
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.3.0"
 html5ever-atoms = "0.3"
 ipc-channel = "0.7"
 libc = "0.2"
--- a/servo/components/msg/Cargo.toml
+++ b/servo/components/msg/Cargo.toml
@@ -6,14 +6,14 @@ license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "msg"
 path = "lib.rs"
 
 [dependencies]
 bitflags = "0.7"
-cssparser = "0.12.1"
+cssparser = "0.13"
 heapsize = "0.3.0"
 heapsize_derive = "0.1"
 serde = "0.9"
 serde_derive = "0.9"
 webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -30,17 +30,17 @@ audio-video-metadata = "0.1.2"
 atomic_refcell = "0.1"
 base64 = "0.4.1"
 bitflags = "0.7"
 bluetooth_traits = {path = "../bluetooth_traits"}
 byteorder = "1.0"
 canvas_traits = {path = "../canvas_traits"}
 caseless = "0.1.0"
 cookie = "0.6"
-cssparser = "0.12.1"
+cssparser = "0.13"
 deny_public_fields = {path = "../deny_public_fields"}
 devtools_traits = {path = "../devtools_traits"}
 dom_struct = {path = "../dom_struct"}
 domobject_derive = {path = "../domobject_derive"}
 encoding = "0.2"
 euclid = "0.11"
 fnv = "1.0"
 gfx_traits = {path = "../gfx_traits"}
--- a/servo/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/servo/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1845,16 +1845,17 @@ class CGImports(CGWrapper):
         """
         if ignored_warnings is None:
             ignored_warnings = [
                 'non_camel_case_types',
                 'non_upper_case_globals',
                 'unused_imports',
                 'unused_variables',
                 'unused_assignments',
+                'unused_mut',
             ]
 
         def componentTypes(type):
             if type.isType() and type.nullable():
                 type = type.unroll()
             if type.isUnion():
                 return type.flatMemberTypes
             if type.isDictionary():
--- a/servo/components/script/dom/dissimilaroriginlocation.rs
+++ b/servo/components/script/dom/dissimilaroriginlocation.rs
@@ -40,16 +40,17 @@ impl DissimilarOriginLocation {
     }
 
     pub fn new(window: &DissimilarOriginWindow) -> Root<DissimilarOriginLocation> {
         reflect_dom_object(box DissimilarOriginLocation::new_inherited(window),
                            window,
                            DissimilarOriginLocationBinding::Wrap)
     }
 
+    #[allow(dead_code)]
     pub fn origin(&self) -> &MutableOrigin {
         self.window.origin()
     }
 }
 
 impl DissimilarOriginLocationMethods for DissimilarOriginLocation {
     // https://html.spec.whatwg.org/multipage/#dom-location-href
     fn GetHref(&self) -> Fallible<USVString> {
--- a/servo/components/script/dom/dissimilaroriginwindow.rs
+++ b/servo/components/script/dom/dissimilaroriginwindow.rs
@@ -60,16 +60,17 @@ impl DissimilarOriginWindow {
                                                     timer_event_chan,
                                                     global_to_clone_from.origin().clone()),
             browsing_context: JS::from_ref(browsing_context),
             location: MutNullableJS::new(None),
         };
         unsafe { DissimilarOriginWindowBinding::Wrap(cx, win) }
     }
 
+    #[allow(dead_code)]
     pub fn origin(&self) -> &MutableOrigin {
         self.globalscope.origin()
     }
 }
 
 impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
     // https://html.spec.whatwg.org/multipage/#dom-window
     fn Window(&self) -> Root<BrowsingContext> {
--- a/servo/components/script/dom/location.rs
+++ b/servo/components/script/dom/location.rs
@@ -56,16 +56,17 @@ impl Location {
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-location-reload
     pub fn reload_without_origin_check(&self) {
         self.window.load_url(self.get_url(), true, true, None);
     }
 
+    #[allow(dead_code)]
     pub fn origin(&self) -> &MutableOrigin {
         self.window.origin()
     }
 }
 
 impl LocationMethods for Location {
     // https://html.spec.whatwg.org/multipage/#dom-location-assign
     fn Assign(&self, url: USVString) -> ErrorResult {
--- a/servo/components/script_layout_interface/Cargo.toml
+++ b/servo/components/script_layout_interface/Cargo.toml
@@ -8,17 +8,17 @@ publish = false
 [lib]
 name = "script_layout_interface"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4"
 atomic_refcell = "0.1"
 canvas_traits = {path = "../canvas_traits"}
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.3.0"
 heapsize_derive = "0.1"
 html5ever-atoms = "0.3"
 ipc-channel = "0.7"
 libc = "0.2"
 log = "0.3.5"
--- a/servo/components/selectors/Cargo.toml
+++ b/servo/components/selectors/Cargo.toml
@@ -13,12 +13,12 @@ license = "MPL-2.0"
 
 [lib]
 name = "selectors"
 path = "lib.rs"
 
 [dependencies]
 bitflags = "0.7"
 matches = "0.1"
-cssparser = "0.12.1"
+cssparser = "0.13"
 fnv = "1.0"
 precomputed-hash = "0.1"
 smallvec = "0.3"
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -24,17 +24,17 @@ gecko_debug = ["nsstring_vendor/gecko_de
 
 [dependencies]
 app_units = "0.4"
 atomic_refcell = "0.1"
 bitflags = "0.7"
 bit-vec = "0.4.3"
 byteorder = "1.0"
 cfg-if = "0.1.0"
-cssparser = "0.12.1"
+cssparser = "0.13.1"
 encoding = {version = "0.2", optional = true}
 euclid = "0.11"
 fnv = "1.0"
 heapsize = {version = "0.3.0", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 html5ever-atoms = {version = "0.3", optional = true}
 lazy_static = "0.2"
 log = "0.3"
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -619,16 +619,17 @@ mod bindings {
             .hide_type("nsAString_internal")
             .raw_line("pub use nsstring::{nsACString, nsAString, nsString};")
             .raw_line("type nsACString_internal = nsACString;")
             .raw_line("type nsAString_internal = nsAString;")
             .whitelisted_function("Servo_.*")
             .whitelisted_function("Gecko_.*");
         let structs_types = [
             "mozilla::css::URLValue",
+            "mozilla::Side",
             "RawGeckoAnimationPropertySegment",
             "RawGeckoComputedTiming",
             "RawGeckoDocument",
             "RawGeckoElement",
             "RawGeckoKeyframeList",
             "RawGeckoComputedKeyframeValuesList",
             "RawGeckoFontFaceRuleList",
             "RawGeckoNode",
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -1,14 +1,15 @@
 /* automatically generated by rust-bindgen */
 
 pub use nsstring::{nsACString, nsAString, nsString};
 type nsACString_internal = nsACString;
 type nsAString_internal = nsAString;
 use gecko_bindings::structs::mozilla::css::URLValue;
+use gecko_bindings::structs::mozilla::Side;
 use gecko_bindings::structs::RawGeckoAnimationPropertySegment;
 use gecko_bindings::structs::RawGeckoComputedTiming;
 use gecko_bindings::structs::RawGeckoDocument;
 use gecko_bindings::structs::RawGeckoElement;
 use gecko_bindings::structs::RawGeckoKeyframeList;
 use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;
 use gecko_bindings::structs::RawGeckoFontFaceRuleList;
 use gecko_bindings::structs::RawGeckoNode;
@@ -715,16 +716,31 @@ extern "C" {
 }
 extern "C" {
     pub fn Gecko_AtomEqualsUTF8IgnoreCase(aAtom: *mut nsIAtom,
                                           aString:
                                               *const ::std::os::raw::c_char,
                                           aLength: u32) -> bool;
 }
 extern "C" {
+    pub fn Gecko_EnsureMozBorderColors(aBorder: *mut nsStyleBorder);
+}
+extern "C" {
+    pub fn Gecko_ClearMozBorderColors(aBorder: *mut nsStyleBorder,
+                                      aSide: Side);
+}
+extern "C" {
+    pub fn Gecko_AppendMozBorderColors(aBorder: *mut nsStyleBorder,
+                                       aSide: Side, aColor: nscolor);
+}
+extern "C" {
+    pub fn Gecko_CopyMozBorderColors(aDest: *mut nsStyleBorder,
+                                     aSrc: *const nsStyleBorder, aSide: Side);
+}
+extern "C" {
     pub fn Gecko_FontFamilyList_Clear(aList: *mut FontFamilyList);
 }
 extern "C" {
     pub fn Gecko_FontFamilyList_AppendNamed(aList: *mut FontFamilyList,
                                             aName: *mut nsIAtom,
                                             aQuoted: bool);
 }
 extern "C" {
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -4005,36 +4005,37 @@ pub mod root {
             mozSuppressed = 54,
             mozHandlerClickToPlay = 55,
             mozHandlerVulnerableUpdatable = 56,
             mozHandlerVulnerableNoUpdate = 57,
             mozHandlerDisabled = 58,
             mozHandlerBlocked = 59,
             mozHandlerCrashed = 60,
             mozMathIncrementScriptLevel = 61,
-            required = 62,
-            optional = 63,
-            valid = 64,
-            invalid = 65,
-            inRange = 66,
-            outOfRange = 67,
-            defaultPseudo = 68,
-            placeholderShown = 69,
-            mozReadOnly = 70,
-            mozReadWrite = 71,
-            mozSubmitInvalid = 72,
-            mozUIInvalid = 73,
-            mozUIValid = 74,
-            mozMeterOptimum = 75,
-            mozMeterSubOptimum = 76,
-            mozMeterSubSubOptimum = 77,
-            mozPlaceholder = 78,
-            Count = 79,
-            NotPseudo = 80,
-            MAX = 81,
+            mozAutofill = 62,
+            required = 63,
+            optional = 64,
+            valid = 65,
+            invalid = 66,
+            inRange = 67,
+            outOfRange = 68,
+            defaultPseudo = 69,
+            placeholderShown = 70,
+            mozReadOnly = 71,
+            mozReadWrite = 72,
+            mozSubmitInvalid = 73,
+            mozUIInvalid = 74,
+            mozUIValid = 75,
+            mozMeterOptimum = 76,
+            mozMeterSubOptimum = 77,
+            mozMeterSubSubOptimum = 78,
+            mozPlaceholder = 79,
+            Count = 80,
+            NotPseudo = 81,
+            MAX = 82,
         }
         pub const SERVO_PREF_ENABLED_align_content: bool = false;
         pub const SERVO_PREF_ENABLED_align_items: bool = false;
         pub const SERVO_PREF_ENABLED_align_self: bool = false;
         pub const SERVO_PREF_ENABLED_all: bool = true;
         pub const SERVO_PREF_ENABLED_animation: bool = false;
         pub const SERVO_PREF_ENABLED_animation_delay: bool = false;
         pub const SERVO_PREF_ENABLED_animation_direction: bool = false;
@@ -4655,16 +4656,34 @@ pub mod root {
             impl Clone for Color {
                 fn clone(&self) -> Self { *self }
             }
             pub type IntPoint = [u32; 2usize];
             pub type IntMargin = [u32; 4usize];
             pub type IntRect = [u32; 4usize];
             pub type Matrix4x4 = [u32; 16usize];
             #[repr(C)]
+            #[derive(Debug, Copy)]
+            pub struct FontVariation {
+                pub _bindgen_opaque_blob: [u32; 2usize],
+            }
+            #[test]
+            fn bindgen_test_layout_FontVariation() {
+                assert_eq!(::std::mem::size_of::<FontVariation>() , 8usize ,
+                           concat ! (
+                           "Size of: " , stringify ! ( FontVariation ) ));
+                assert_eq! (::std::mem::align_of::<FontVariation>() , 4usize ,
+                            concat ! (
+                            "Alignment of " , stringify ! ( FontVariation )
+                            ));
+            }
+            impl Clone for FontVariation {
+                fn clone(&self) -> Self { *self }
+            }
+            #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct SourceSurface([u8; 0]);
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct DrawTarget([u8; 0]);
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct Path([u8; 0]);
@@ -9314,16 +9333,34 @@ pub mod root {
                     "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
                     stringify ! ( _unused2 ) ));
     }
     impl Clone for _IO_FILE {
         fn clone(&self) -> Self { *self }
     }
     pub type FILE = root::_IO_FILE;
     pub type va_list = root::__builtin_va_list;
+    #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct InfallibleAllocPolicy {
+        pub _address: u8,
+    }
+    #[test]
+    fn bindgen_test_layout_InfallibleAllocPolicy() {
+        assert_eq!(::std::mem::size_of::<InfallibleAllocPolicy>() , 1usize ,
+                   concat ! (
+                   "Size of: " , stringify ! ( InfallibleAllocPolicy ) ));
+        assert_eq! (::std::mem::align_of::<InfallibleAllocPolicy>() , 1usize ,
+                    concat ! (
+                    "Alignment of " , stringify ! ( InfallibleAllocPolicy )
+                    ));
+    }
+    impl Clone for InfallibleAllocPolicy {
+        fn clone(&self) -> Self { *self }
+    }
     /**
  * MozRefCountType is Mozilla's reference count type.
  *
  * We use the same type to represent the refcount of RefCounted objects
  * as well, in order to be able to use the leak detection facilities
  * that are implemented by XPCOM.
  *
  * Note that this type is not in the mozilla namespace so that it is
@@ -9606,16 +9643,17 @@ pub mod root {
         NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSEXML
             = 2152924158,
         NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT
             = 2152924159,
         NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC
             = 2152924160,
         NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC
             = 2152924161,
+        NS_ERROR_DOM_JS_DECODING_ERROR = 2152924162,
         NS_SUCCESS_DOM_NO_OPERATION = 5439489,
         NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW = 5439490,
         NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE = 5439491,
         NS_IMAGELIB_SUCCESS_LOAD_FINISHED = 5505024,
         NS_IMAGELIB_CHANGING_OWNER = 5505025,
         NS_IMAGELIB_ERROR_FAILURE = 2152988677,
         NS_IMAGELIB_ERROR_NO_DECODER = 2152988678,
         NS_IMAGELIB_ERROR_NOT_FINISHED = 2152988679,
@@ -12543,17 +12581,17 @@ pub mod root {
         pub mCachedRootElement: *mut root::mozilla::dom::Element,
         pub mNodeInfoManager: *mut root::nsNodeInfoManager,
         pub mCSSLoader: root::RefPtr<root::mozilla::css::Loader>,
         pub mStyleImageLoader: root::RefPtr<root::mozilla::css::ImageLoader>,
         pub mAttrStyleSheet: root::RefPtr<root::nsHTMLStyleSheet>,
         pub mStyleAttrStyleSheet: root::RefPtr<root::nsHTMLCSSStyleSheet>,
         pub mImageTracker: root::RefPtr<root::mozilla::dom::ImageTracker>,
         pub mActivityObservers: root::nsAutoPtr<()>,
-        pub mLinksToUpdate: [u64; 6usize],
+        pub mLinksToUpdate: [u64; 3usize],
         pub mAnimationController: root::RefPtr<root::nsSMILAnimationController>,
         pub mPropertyTable: root::nsPropertyTable,
         pub mExtraPropertyTables: root::nsTArray<root::nsAutoPtr<root::nsPropertyTable>>,
         pub mChildrenCollection: root::nsCOMPtr<root::nsIHTMLCollection>,
         pub mFontFaceSet: root::RefPtr<root::mozilla::dom::FontFaceSet>,
         pub mLastFocusTime: root::mozilla::TimeStamp,
         pub _bitfield_1: u8,
         pub _bitfield_2: u8,
@@ -12607,17 +12645,17 @@ pub mod root {
         pub mBFCacheEntry: *mut root::nsIBFCacheEntry,
         pub mBaseTarget: ::nsstring::nsStringRepr,
         pub mStateObjectContainer: root::nsCOMPtr<root::nsIStructuredCloneContainer>,
         pub mStateObjectCached: root::nsCOMPtr<root::nsIVariant>,
         pub mInSyncOperationCount: u32,
         pub mXPathEvaluator: root::RefPtr<root::mozilla::dom::XPathEvaluator>,
         pub mAnonymousContents: root::nsTArray<root::RefPtr<root::mozilla::dom::AnonymousContent>>,
         pub mBlockDOMContentLoaded: u32,
-        pub mDOMMediaQueryLists: root::PRCList,
+        pub mDOMMediaQueryLists: root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>,
         pub mUseCounters: [u64; 2usize],
         pub mChildDocumentUseCounters: [u64; 2usize],
         pub mNotifiedPageForUseCounter: [u64; 2usize],
         pub mUserHasInteracted: bool,
         pub mPageUnloadingEventTimeStamp: root::mozilla::TimeStamp,
         pub mDocGroup: root::RefPtr<root::mozilla::dom::DocGroup>,
         pub mTrackingScripts: [u64; 6usize],
     }
@@ -12891,19 +12929,20 @@ pub mod root {
         eXUL = 5,
     }
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum nsIDocument_Tri { eTriUnset = 0, eTriFalse = 1, eTriTrue = 2, }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsIDocument_FrameRequest([u8; 0]);
+    pub const nsIDocument_kSegmentSize: usize = 128;
     #[test]
     fn bindgen_test_layout_nsIDocument() {
-        assert_eq!(::std::mem::size_of::<nsIDocument>() , 912usize , concat !
+        assert_eq!(::std::mem::size_of::<nsIDocument>() , 896usize , concat !
                    ( "Size of: " , stringify ! ( nsIDocument ) ));
         assert_eq! (::std::mem::align_of::<nsIDocument>() , 8usize , concat !
                     ( "Alignment of " , stringify ! ( nsIDocument ) ));
     }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsIDocShell([u8; 0]);
     /**
@@ -16982,43 +17021,16 @@ pub mod root {
         assert_eq! (::std::mem::align_of::<nsExpirationState>() , 4usize ,
                     concat ! (
                     "Alignment of " , stringify ! ( nsExpirationState ) ));
     }
     impl Clone for nsExpirationState {
         fn clone(&self) -> Self { *self }
     }
     #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct PRCListStr {
-        pub next: *mut root::PRCList,
-        pub prev: *mut root::PRCList,
-    }
-    #[test]
-    fn bindgen_test_layout_PRCListStr() {
-        assert_eq!(::std::mem::size_of::<PRCListStr>() , 16usize , concat ! (
-                   "Size of: " , stringify ! ( PRCListStr ) ));
-        assert_eq! (::std::mem::align_of::<PRCListStr>() , 8usize , concat ! (
-                    "Alignment of " , stringify ! ( PRCListStr ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const PRCListStr ) ) . next as * const _ as
-                    usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( PRCListStr ) , "::"
-                    , stringify ! ( next ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const PRCListStr ) ) . prev as * const _ as
-                    usize } , 8usize , concat ! (
-                    "Alignment of field: " , stringify ! ( PRCListStr ) , "::"
-                    , stringify ! ( prev ) ));
-    }
-    impl Clone for PRCListStr {
-        fn clone(&self) -> Self { *self }
-    }
-    pub type PRCList = root::PRCListStr;
-    #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct gfxUserFontSet([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct imgIRequest {
         pub _base: root::nsIRequest,
     }
     #[repr(C)]
@@ -17071,16 +17083,31 @@ pub mod root {
         imgIRequest__bindgen_ty_2::CORS_USE_CREDENTIALS;
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum imgIRequest__bindgen_ty_2 {
         CORS_NONE = 1,
         CORS_ANONYMOUS = 2,
         CORS_USE_CREDENTIALS = 3,
     }
+    pub const imgIRequest_CATEGORY_FRAME_INIT: root::imgIRequest__bindgen_ty_3
+              =
+        imgIRequest__bindgen_ty_3::CATEGORY_FRAME_INIT;
+    pub const imgIRequest_CATEGORY_SIZE_QUERY: root::imgIRequest__bindgen_ty_3
+              =
+        imgIRequest__bindgen_ty_3::CATEGORY_SIZE_QUERY;
+    pub const imgIRequest_CATEGORY_DISPLAY: root::imgIRequest__bindgen_ty_3 =
+        imgIRequest__bindgen_ty_3::CATEGORY_DISPLAY;
+    #[repr(u32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum imgIRequest__bindgen_ty_3 {
+        CATEGORY_FRAME_INIT = 1,
+        CATEGORY_SIZE_QUERY = 2,
+        CATEGORY_DISPLAY = 4,
+    }
     #[test]
     fn bindgen_test_layout_imgIRequest() {
         assert_eq!(::std::mem::size_of::<imgIRequest>() , 8usize , concat ! (
                    "Size of: " , stringify ! ( imgIRequest ) ));
         assert_eq! (::std::mem::align_of::<imgIRequest>() , 8usize , concat !
                     ( "Alignment of " , stringify ! ( imgIRequest ) ));
     }
     impl Clone for imgIRequest {
@@ -17720,43 +17747,17 @@ pub mod root {
         assert_eq! (unsafe {
                     & ( * ( 0 as * const gfxFontFeatureValueSet ) ) .
                     mFontFeatureValues as * const _ as usize } , 16usize ,
                     concat ! (
                     "Alignment of field: " , stringify ! (
                     gfxFontFeatureValueSet ) , "::" , stringify ! (
                     mFontFeatureValues ) ));
     }
-    #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct gfxFontVariation {
-        pub mTag: u32,
-        pub mValue: f32,
-    }
-    #[test]
-    fn bindgen_test_layout_gfxFontVariation() {
-        assert_eq!(::std::mem::size_of::<gfxFontVariation>() , 8usize , concat
-                   ! ( "Size of: " , stringify ! ( gfxFontVariation ) ));
-        assert_eq! (::std::mem::align_of::<gfxFontVariation>() , 4usize ,
-                    concat ! (
-                    "Alignment of " , stringify ! ( gfxFontVariation ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const gfxFontVariation ) ) . mTag as *
-                    const _ as usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( gfxFontVariation )
-                    , "::" , stringify ! ( mTag ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const gfxFontVariation ) ) . mValue as *
-                    const _ as usize } , 4usize , concat ! (
-                    "Alignment of field: " , stringify ! ( gfxFontVariation )
-                    , "::" , stringify ! ( mValue ) ));
-    }
-    impl Clone for gfxFontVariation {
-        fn clone(&self) -> Self { *self }
-    }
+    pub type gfxFontVariation = root::mozilla::gfx::FontVariation;
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct gfxFontStyle([u8; 0]);
     pub const kGenericFont_NONE: u8 = 0;
     pub const kGenericFont_moz_variable: u8 = 0;
     pub const kGenericFont_moz_fixed: u8 = 1;
     pub const kGenericFont_serif: u8 = 2;
     pub const kGenericFont_sans_serif: u8 = 4;
@@ -17781,17 +17782,17 @@ pub mod root {
         pub stretch: i16,
         pub kerning: u8,
         pub synthesis: u8,
         pub size: root::nscoord,
         pub sizeAdjust: f32,
         pub alternateValues: root::nsTArray<root::gfxAlternateValue>,
         pub featureValueLookup: root::RefPtr<root::gfxFontFeatureValueSet>,
         pub fontFeatureSettings: root::nsTArray<root::gfxFontFeature>,
-        pub fontVariationSettings: root::nsTArray<root::gfxFontVariation>,
+        pub fontVariationSettings: root::nsTArray<root::mozilla::gfx::FontVariation>,
         pub languageOverride: u32,
     }
     #[test]
     fn bindgen_test_layout_nsFont() {
         assert_eq!(::std::mem::size_of::<nsFont>() , 88usize , concat ! (
                    "Size of: " , stringify ! ( nsFont ) ));
         assert_eq! (::std::mem::align_of::<nsFont>() , 8usize , concat ! (
                     "Alignment of " , stringify ! ( nsFont ) ));
@@ -23509,16 +23510,17 @@ pub mod root {
         pub mFirstProxy: *mut ::std::os::raw::c_void,
         pub mValidator: *mut root::imgCacheValidator,
         pub mRedirectCallback: root::nsCOMPtr<root::nsIAsyncVerifyRedirectCallback>,
         pub mNewRedirectChannel: root::nsCOMPtr<root::nsIChannel>,
         pub mInnerWindowId: u64,
         pub mCORSMode: i32,
         pub mReferrerPolicy: root::imgRequest_ReferrerPolicy,
         pub mImageErrorCode: root::nsresult,
+        pub mBoostCategoriesRequested: u32,
         pub mMutex: root::mozilla::Mutex,
         pub mProgressTracker: root::RefPtr<root::mozilla::image::ProgressTracker>,
         pub mImage: root::RefPtr<root::mozilla::image::Image>,
         pub _bitfield_1: u8,
         pub __bindgen_padding_0: [u8; 7usize],
     }
     pub type imgRequest_Image = root::mozilla::image::Image;
     pub type imgRequest_ImageCacheKey = root::mozilla::image::ImageCacheKey;
@@ -28161,771 +28163,795 @@ pub mod root {
                    root::RefPtr<root::mozilla::StyleSheet> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::StyleSheet>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::StyleSheet> ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_42() {
+        assert_eq!(::std::mem::size_of::<root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>>()
+                   , 24usize , concat ! (
+                   "Size of template specialization: " , stringify ! (
+                   root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>
+                   ) ));
+        assert_eq!(::std::mem::align_of::<root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>>()
+                   , 8usize , concat ! (
+                   "Alignment of template specialization: " , stringify ! (
+                   root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>
+                   ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_43() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::Element>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::Element> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::Element>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::Element> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_43() {
+    fn __bindgen_test_layout_template_44() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::Element>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::Element>> )
                    ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::Element>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::Element>> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_44() {
+    fn __bindgen_test_layout_template_45() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIObserver>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIObserver> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIObserver>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIObserver> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_45() {
+    fn __bindgen_test_layout_template_46() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::nsCOMPtr<root::nsIObserver>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::nsCOMPtr<root::nsIObserver>> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::nsCOMPtr<root::nsIObserver>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::nsCOMPtr<root::nsIObserver>> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_46() {
+    fn __bindgen_test_layout_template_47() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsIDocument>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIDocument> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsIDocument>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIDocument> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_47() {
+    fn __bindgen_test_layout_template_48() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsContentList>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsContentList> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsContentList>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsContentList> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_48() {
+    fn __bindgen_test_layout_template_49() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsINode>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsINode> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsINode>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsINode> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_49() {
+    fn __bindgen_test_layout_template_50() {
+        assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::mozilla::dom::Link>>()
+                   , 8usize , concat ! (
+                   "Size of template specialization: " , stringify ! (
+                   root::nsCOMPtr<root::mozilla::dom::Link> ) ));
+        assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::mozilla::dom::Link>>()
+                   , 8usize , concat ! (
+                   "Alignment of template specialization: " , stringify ! (
+                   root::nsCOMPtr<root::mozilla::dom::Link> ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_51() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIWeakReference>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIWeakReference> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIWeakReference>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIWeakReference> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_50() {
+    fn __bindgen_test_layout_template_52() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_51() {
+    fn __bindgen_test_layout_template_53() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::nsRect>>() ,
                    8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::nsRect> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::nsRect>>() ,
                    8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::nsRect> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_52() {
+    fn __bindgen_test_layout_template_54() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsBidi>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsBidi> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsBidi>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsBidi> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_53() {
+    fn __bindgen_test_layout_template_55() {
         assert_eq!(::std::mem::size_of::<[u64; 29usize]>() , 232usize , concat
                    ! (
                    "Size of template specialization: " , stringify ! (
                    [u64; 29usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 29usize]>() , 8usize , concat
                    ! (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 29usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_54() {
+    fn __bindgen_test_layout_template_56() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<*mut root::nsIContent>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::nsIContent> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<*mut root::nsIContent>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::nsIContent> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_55() {
+    fn __bindgen_test_layout_template_57() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::mozilla::dom::CSSValue>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::dom::CSSValue> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::mozilla::dom::CSSValue>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::dom::CSSValue> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_56() {
+    fn __bindgen_test_layout_template_58() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_57() {
+    fn __bindgen_test_layout_template_59() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsISupports>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsISupports> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsISupports>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsISupports> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_58() {
+    fn __bindgen_test_layout_template_60() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIRunnable>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIRunnable> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIRunnable>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIRunnable> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_59() {
+    fn __bindgen_test_layout_template_61() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsIContent>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIContent> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsIContent>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIContent> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_60() {
+    fn __bindgen_test_layout_template_62() {
         assert_eq!(::std::mem::size_of::<[u64; 6usize]>() , 48usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 6usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 6usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 6usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_61() {
+    fn __bindgen_test_layout_template_63() {
         assert_eq!(::std::mem::size_of::<root::mozilla::OwningNonNull<root::nsINode>>()
                    , 16usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::nsINode> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::OwningNonNull<root::nsINode>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::nsINode> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_62() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
-    fn __bindgen_test_layout_template_63() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_64() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_65() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_66() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_67() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_68() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_68() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_69() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_70() {
         assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 4usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 4usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_71() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_72() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_73() {
         assert_eq!(::std::mem::size_of::<u32>() , 4usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u32 )
                    ));
         assert_eq!(::std::mem::align_of::<u32>() , 4usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u32 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_72() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
-    fn __bindgen_test_layout_template_73() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_74() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_75() {
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_76() {
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_77() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<f64>>() , 8usize ,
                    concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<f64> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<f64>>() , 8usize ,
                    concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<f64> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_76() {
+    fn __bindgen_test_layout_template_78() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_77() {
+    fn __bindgen_test_layout_template_79() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_78() {
+    fn __bindgen_test_layout_template_80() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::ProfilerBacktrace,
                                                root::ProfilerBacktraceDestructor>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::ProfilerBacktrace,
                          root::ProfilerBacktraceDestructor>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::ProfilerBacktrace,
                                                 root::ProfilerBacktraceDestructor>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::ProfilerBacktrace,
                          root::ProfilerBacktraceDestructor>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_79() {
+    fn __bindgen_test_layout_template_81() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::FontFamilyName>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FontFamilyName> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::FontFamilyName>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FontFamilyName> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_80() {
+    fn __bindgen_test_layout_template_82() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<::std::os::raw::c_uint>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<::std::os::raw::c_uint> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<::std::os::raw::c_uint>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<::std::os::raw::c_uint> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_81() {
+    fn __bindgen_test_layout_template_83() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_82() {
+    fn __bindgen_test_layout_template_84() {
         assert_eq!(::std::mem::size_of::<root::nsPtrHashKey<root::nsIFrame>>()
                    , 16usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsPtrHashKey<root::nsIFrame> ) ));
         assert_eq!(::std::mem::align_of::<root::nsPtrHashKey<root::nsIFrame>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsPtrHashKey<root::nsIFrame> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_83() {
+    fn __bindgen_test_layout_template_85() {
         assert_eq!(::std::mem::size_of::<[u64; 6usize]>() , 48usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 6usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 6usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 6usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_84() {
+    fn __bindgen_test_layout_template_86() {
         assert_eq!(::std::mem::size_of::<root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>>()
                    , 16usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_85() {
+    fn __bindgen_test_layout_template_87() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::ProxyBehaviour>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::ProxyBehaviour> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::ProxyBehaviour>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::ProxyBehaviour> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_86() {
+    fn __bindgen_test_layout_template_88() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::mozilla::URLExtraData>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::URLExtraData> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::mozilla::URLExtraData>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::URLExtraData> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_87() {
+    fn __bindgen_test_layout_template_89() {
         assert_eq!(::std::mem::size_of::<root::nsMainThreadPtrHolder<root::nsIURI>>()
                    , 24usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsMainThreadPtrHolder<root::nsIURI> ) ));
         assert_eq!(::std::mem::align_of::<root::nsMainThreadPtrHolder<root::nsIURI>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsMainThreadPtrHolder<root::nsIURI> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_88() {
+    fn __bindgen_test_layout_template_90() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsCSSValueList>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValueList> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsCSSValueList>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValueList> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_89() {
+    fn __bindgen_test_layout_template_91() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsCSSValueList,
                                                root::mozilla::DefaultDelete<root::nsCSSValueList>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValueList,
                          root::mozilla::DefaultDelete<root::nsCSSValueList>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsCSSValueList,
                                                 root::mozilla::DefaultDelete<root::nsCSSValueList>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValueList,
                          root::mozilla::DefaultDelete<root::nsCSSValueList>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_90() {
+    fn __bindgen_test_layout_template_92() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsCSSValuePairList>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValuePairList> )
                    ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsCSSValuePairList>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValuePairList> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_91() {
+    fn __bindgen_test_layout_template_93() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsCSSValuePairList,
                                                root::mozilla::DefaultDelete<root::nsCSSValuePairList>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValuePairList,
                          root::mozilla::DefaultDelete<root::nsCSSValuePairList>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsCSSValuePairList,
                                                 root::mozilla::DefaultDelete<root::nsCSSValuePairList>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValuePairList,
                          root::mozilla::DefaultDelete<root::nsCSSValuePairList>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_92() {
+    fn __bindgen_test_layout_template_94() {
         assert_eq!(::std::mem::size_of::<[u64; 2usize]>() , 16usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 2usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 2usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_93() {
+    fn __bindgen_test_layout_template_95() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_94() {
+    fn __bindgen_test_layout_template_96() {
         assert_eq!(::std::mem::size_of::<[u32; 3usize]>() , 12usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 3usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 3usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 3usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_95() {
+    fn __bindgen_test_layout_template_97() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsStyleImageRequest>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsStyleImageRequest> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsStyleImageRequest>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsStyleImageRequest> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_96() {
+    fn __bindgen_test_layout_template_98() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsStyleSides>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsStyleSides> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsStyleSides>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsStyleSides> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_97() {
+    fn __bindgen_test_layout_template_99() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsStyleSides,
                                                root::mozilla::DefaultDelete<root::nsStyleSides>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsStyleSides,
                          root::mozilla::DefaultDelete<root::nsStyleSides>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsStyleSides,
                                                 root::mozilla::DefaultDelete<root::nsStyleSides>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsStyleSides,
                          root::mozilla::DefaultDelete<root::nsStyleSides>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_98() {
+    fn __bindgen_test_layout_template_100() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::CachedBorderImageData>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::CachedBorderImageData> )
                    ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::CachedBorderImageData>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::CachedBorderImageData> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_99() {
+    fn __bindgen_test_layout_template_101() {
         assert_eq!(::std::mem::size_of::<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>()
                    , 32usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr> ) ));
         assert_eq!(::std::mem::align_of::<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_100() {
+    fn __bindgen_test_layout_template_102() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::std::pair<::nsstring::nsStringRepr,
                                                      ::nsstring::nsStringRepr>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::std::pair<::nsstring::nsStringRepr,
                                                       ::nsstring::nsStringRepr>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_101() {
+    fn __bindgen_test_layout_template_103() {
         assert_eq!(::std::mem::size_of::<[u64; 18usize]>() , 144usize , concat
                    ! (
                    "Size of template specialization: " , stringify ! (
                    [u64; 18usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 18usize]>() , 8usize , concat
                    ! (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 18usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_102() {
+    fn __bindgen_test_layout_template_104() {
         assert_eq!(::std::mem::size_of::<root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_103() {
+    fn __bindgen_test_layout_template_105() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_104() {
+    fn __bindgen_test_layout_template_106() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::DOMRect>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMRect> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::DOMRect>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMRect> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_105() {
+    fn __bindgen_test_layout_template_107() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_106() {
+    fn __bindgen_test_layout_template_108() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<*mut root::mozilla::css::DocumentRule>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::mozilla::css::DocumentRule> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<*mut root::mozilla::css::DocumentRule>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::mozilla::css::DocumentRule> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_107() {
+    fn __bindgen_test_layout_template_109() {
         assert_eq!(::std::mem::size_of::<root::nsAutoPtr<root::nsMediaQuery>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsAutoPtr<root::nsMediaQuery> ) ));
         assert_eq!(::std::mem::align_of::<root::nsAutoPtr<root::nsMediaQuery>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsAutoPtr<root::nsMediaQuery> ) ));
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -3957,36 +3957,37 @@ pub mod root {
             mozSuppressed = 54,
             mozHandlerClickToPlay = 55,
             mozHandlerVulnerableUpdatable = 56,
             mozHandlerVulnerableNoUpdate = 57,
             mozHandlerDisabled = 58,
             mozHandlerBlocked = 59,
             mozHandlerCrashed = 60,
             mozMathIncrementScriptLevel = 61,
-            required = 62,
-            optional = 63,
-            valid = 64,
-            invalid = 65,
-            inRange = 66,
-            outOfRange = 67,
-            defaultPseudo = 68,
-            placeholderShown = 69,
-            mozReadOnly = 70,
-            mozReadWrite = 71,
-            mozSubmitInvalid = 72,
-            mozUIInvalid = 73,
-            mozUIValid = 74,
-            mozMeterOptimum = 75,
-            mozMeterSubOptimum = 76,
-            mozMeterSubSubOptimum = 77,
-            mozPlaceholder = 78,
-            Count = 79,
-            NotPseudo = 80,
-            MAX = 81,
+            mozAutofill = 62,
+            required = 63,
+            optional = 64,
+            valid = 65,
+            invalid = 66,
+            inRange = 67,
+            outOfRange = 68,
+            defaultPseudo = 69,
+            placeholderShown = 70,
+            mozReadOnly = 71,
+            mozReadWrite = 72,
+            mozSubmitInvalid = 73,
+            mozUIInvalid = 74,
+            mozUIValid = 75,
+            mozMeterOptimum = 76,
+            mozMeterSubOptimum = 77,
+            mozMeterSubSubOptimum = 78,
+            mozPlaceholder = 79,
+            Count = 80,
+            NotPseudo = 81,
+            MAX = 82,
         }
         pub const SERVO_PREF_ENABLED_align_content: bool = false;
         pub const SERVO_PREF_ENABLED_align_items: bool = false;
         pub const SERVO_PREF_ENABLED_align_self: bool = false;
         pub const SERVO_PREF_ENABLED_all: bool = true;
         pub const SERVO_PREF_ENABLED_animation: bool = false;
         pub const SERVO_PREF_ENABLED_animation_delay: bool = false;
         pub const SERVO_PREF_ENABLED_animation_direction: bool = false;
@@ -4606,16 +4607,34 @@ pub mod root {
             impl Clone for Color {
                 fn clone(&self) -> Self { *self }
             }
             pub type IntPoint = [u32; 2usize];
             pub type IntMargin = [u32; 4usize];
             pub type IntRect = [u32; 4usize];
             pub type Matrix4x4 = [u32; 16usize];
             #[repr(C)]
+            #[derive(Debug, Copy)]
+            pub struct FontVariation {
+                pub _bindgen_opaque_blob: [u32; 2usize],
+            }
+            #[test]
+            fn bindgen_test_layout_FontVariation() {
+                assert_eq!(::std::mem::size_of::<FontVariation>() , 8usize ,
+                           concat ! (
+                           "Size of: " , stringify ! ( FontVariation ) ));
+                assert_eq! (::std::mem::align_of::<FontVariation>() , 4usize ,
+                            concat ! (
+                            "Alignment of " , stringify ! ( FontVariation )
+                            ));
+            }
+            impl Clone for FontVariation {
+                fn clone(&self) -> Self { *self }
+            }
+            #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct SourceSurface([u8; 0]);
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct DrawTarget([u8; 0]);
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct Path([u8; 0]);
@@ -8917,16 +8936,34 @@ pub mod root {
         #[repr(C)]
         #[derive(Debug, Copy, Clone)]
         pub struct UniquePtr<T, Deleter> {
             pub mPtr: *mut T,
             pub _phantom_1: ::std::marker::PhantomData<Deleter>,
         }
     }
     pub type va_list = root::__builtin_va_list;
+    #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct InfallibleAllocPolicy {
+        pub _address: u8,
+    }
+    #[test]
+    fn bindgen_test_layout_InfallibleAllocPolicy() {
+        assert_eq!(::std::mem::size_of::<InfallibleAllocPolicy>() , 1usize ,
+                   concat ! (
+                   "Size of: " , stringify ! ( InfallibleAllocPolicy ) ));
+        assert_eq! (::std::mem::align_of::<InfallibleAllocPolicy>() , 1usize ,
+                    concat ! (
+                    "Alignment of " , stringify ! ( InfallibleAllocPolicy )
+                    ));
+    }
+    impl Clone for InfallibleAllocPolicy {
+        fn clone(&self) -> Self { *self }
+    }
     /**
  * MozRefCountType is Mozilla's reference count type.
  *
  * We use the same type to represent the refcount of RefCounted objects
  * as well, in order to be able to use the leak detection facilities
  * that are implemented by XPCOM.
  *
  * Note that this type is not in the mozilla namespace so that it is
@@ -9209,16 +9246,17 @@ pub mod root {
         NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSEXML
             = 2152924158,
         NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT
             = 2152924159,
         NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC
             = 2152924160,
         NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC
             = 2152924161,
+        NS_ERROR_DOM_JS_DECODING_ERROR = 2152924162,
         NS_SUCCESS_DOM_NO_OPERATION = 5439489,
         NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW = 5439490,
         NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE = 5439491,
         NS_IMAGELIB_SUCCESS_LOAD_FINISHED = 5505024,
         NS_IMAGELIB_CHANGING_OWNER = 5505025,
         NS_IMAGELIB_ERROR_FAILURE = 2152988677,
         NS_IMAGELIB_ERROR_NO_DECODER = 2152988678,
         NS_IMAGELIB_ERROR_NOT_FINISHED = 2152988679,
@@ -12078,17 +12116,17 @@ pub mod root {
         pub mCachedRootElement: *mut root::mozilla::dom::Element,
         pub mNodeInfoManager: *mut root::nsNodeInfoManager,
         pub mCSSLoader: root::RefPtr<root::mozilla::css::Loader>,
         pub mStyleImageLoader: root::RefPtr<root::mozilla::css::ImageLoader>,
         pub mAttrStyleSheet: root::RefPtr<root::nsHTMLStyleSheet>,
         pub mStyleAttrStyleSheet: root::RefPtr<root::nsHTMLCSSStyleSheet>,
         pub mImageTracker: root::RefPtr<root::mozilla::dom::ImageTracker>,
         pub mActivityObservers: root::nsAutoPtr<()>,
-        pub mLinksToUpdate: [u64; 5usize],
+        pub mLinksToUpdate: [u64; 3usize],
         pub mAnimationController: root::RefPtr<root::nsSMILAnimationController>,
         pub mPropertyTable: root::nsPropertyTable,
         pub mExtraPropertyTables: root::nsTArray<root::nsAutoPtr<root::nsPropertyTable>>,
         pub mChildrenCollection: root::nsCOMPtr<root::nsIHTMLCollection>,
         pub mFontFaceSet: root::RefPtr<root::mozilla::dom::FontFaceSet>,
         pub mLastFocusTime: root::mozilla::TimeStamp,
         pub _bitfield_1: u8,
         pub _bitfield_2: u8,
@@ -12137,17 +12175,17 @@ pub mod root {
         pub mBFCacheEntry: *mut root::nsIBFCacheEntry,
         pub mBaseTarget: ::nsstring::nsStringRepr,
         pub mStateObjectContainer: root::nsCOMPtr<root::nsIStructuredCloneContainer>,
         pub mStateObjectCached: root::nsCOMPtr<root::nsIVariant>,
         pub mInSyncOperationCount: u32,
         pub mXPathEvaluator: root::RefPtr<root::mozilla::dom::XPathEvaluator>,
         pub mAnonymousContents: root::nsTArray<root::RefPtr<root::mozilla::dom::AnonymousContent>>,
         pub mBlockDOMContentLoaded: u32,
-        pub mDOMMediaQueryLists: root::PRCList,
+        pub mDOMMediaQueryLists: root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>,
         pub mUseCounters: [u64; 2usize],
         pub mChildDocumentUseCounters: [u64; 2usize],
         pub mNotifiedPageForUseCounter: [u64; 2usize],
         pub mUserHasInteracted: bool,
         pub mPageUnloadingEventTimeStamp: root::mozilla::TimeStamp,
         pub mDocGroup: root::RefPtr<root::mozilla::dom::DocGroup>,
         pub mTrackingScripts: [u64; 5usize],
     }
@@ -12421,19 +12459,20 @@ pub mod root {
         eXUL = 5,
     }
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum nsIDocument_Tri { eTriUnset = 0, eTriFalse = 1, eTriTrue = 2, }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsIDocument_FrameRequest([u8; 0]);
+    pub const nsIDocument_kSegmentSize: usize = 128;
     #[test]
     fn bindgen_test_layout_nsIDocument() {
-        assert_eq!(::std::mem::size_of::<nsIDocument>() , 880usize , concat !
+        assert_eq!(::std::mem::size_of::<nsIDocument>() , 872usize , concat !
                    ( "Size of: " , stringify ! ( nsIDocument ) ));
         assert_eq! (::std::mem::align_of::<nsIDocument>() , 8usize , concat !
                     ( "Alignment of " , stringify ! ( nsIDocument ) ));
     }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsIDocShell([u8; 0]);
     /**
@@ -16424,43 +16463,16 @@ pub mod root {
         assert_eq! (::std::mem::align_of::<nsExpirationState>() , 4usize ,
                     concat ! (
                     "Alignment of " , stringify ! ( nsExpirationState ) ));
     }
     impl Clone for nsExpirationState {
         fn clone(&self) -> Self { *self }
     }
     #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct PRCListStr {
-        pub next: *mut root::PRCList,
-        pub prev: *mut root::PRCList,
-    }
-    #[test]
-    fn bindgen_test_layout_PRCListStr() {
-        assert_eq!(::std::mem::size_of::<PRCListStr>() , 16usize , concat ! (
-                   "Size of: " , stringify ! ( PRCListStr ) ));
-        assert_eq! (::std::mem::align_of::<PRCListStr>() , 8usize , concat ! (
-                    "Alignment of " , stringify ! ( PRCListStr ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const PRCListStr ) ) . next as * const _ as
-                    usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( PRCListStr ) , "::"
-                    , stringify ! ( next ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const PRCListStr ) ) . prev as * const _ as
-                    usize } , 8usize , concat ! (
-                    "Alignment of field: " , stringify ! ( PRCListStr ) , "::"
-                    , stringify ! ( prev ) ));
-    }
-    impl Clone for PRCListStr {
-        fn clone(&self) -> Self { *self }
-    }
-    pub type PRCList = root::PRCListStr;
-    #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct gfxUserFontSet([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct imgIRequest {
         pub _base: root::nsIRequest,
     }
     #[repr(C)]
@@ -16513,16 +16525,31 @@ pub mod root {
         imgIRequest__bindgen_ty_2::CORS_USE_CREDENTIALS;
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum imgIRequest__bindgen_ty_2 {
         CORS_NONE = 1,
         CORS_ANONYMOUS = 2,
         CORS_USE_CREDENTIALS = 3,
     }
+    pub const imgIRequest_CATEGORY_FRAME_INIT: root::imgIRequest__bindgen_ty_3
+              =
+        imgIRequest__bindgen_ty_3::CATEGORY_FRAME_INIT;
+    pub const imgIRequest_CATEGORY_SIZE_QUERY: root::imgIRequest__bindgen_ty_3
+              =
+        imgIRequest__bindgen_ty_3::CATEGORY_SIZE_QUERY;
+    pub const imgIRequest_CATEGORY_DISPLAY: root::imgIRequest__bindgen_ty_3 =
+        imgIRequest__bindgen_ty_3::CATEGORY_DISPLAY;
+    #[repr(u32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum imgIRequest__bindgen_ty_3 {
+        CATEGORY_FRAME_INIT = 1,
+        CATEGORY_SIZE_QUERY = 2,
+        CATEGORY_DISPLAY = 4,
+    }
     #[test]
     fn bindgen_test_layout_imgIRequest() {
         assert_eq!(::std::mem::size_of::<imgIRequest>() , 8usize , concat ! (
                    "Size of: " , stringify ! ( imgIRequest ) ));
         assert_eq! (::std::mem::align_of::<imgIRequest>() , 8usize , concat !
                     ( "Alignment of " , stringify ! ( imgIRequest ) ));
     }
     impl Clone for imgIRequest {
@@ -17154,43 +17181,17 @@ pub mod root {
         assert_eq! (unsafe {
                     & ( * ( 0 as * const gfxFontFeatureValueSet ) ) .
                     mFontFeatureValues as * const _ as usize } , 8usize ,
                     concat ! (
                     "Alignment of field: " , stringify ! (
                     gfxFontFeatureValueSet ) , "::" , stringify ! (
                     mFontFeatureValues ) ));
     }
-    #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct gfxFontVariation {
-        pub mTag: u32,
-        pub mValue: f32,
-    }
-    #[test]
-    fn bindgen_test_layout_gfxFontVariation() {
-        assert_eq!(::std::mem::size_of::<gfxFontVariation>() , 8usize , concat
-                   ! ( "Size of: " , stringify ! ( gfxFontVariation ) ));
-        assert_eq! (::std::mem::align_of::<gfxFontVariation>() , 4usize ,
-                    concat ! (
-                    "Alignment of " , stringify ! ( gfxFontVariation ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const gfxFontVariation ) ) . mTag as *
-                    const _ as usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( gfxFontVariation )
-                    , "::" , stringify ! ( mTag ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const gfxFontVariation ) ) . mValue as *
-                    const _ as usize } , 4usize , concat ! (
-                    "Alignment of field: " , stringify ! ( gfxFontVariation )
-                    , "::" , stringify ! ( mValue ) ));
-    }
-    impl Clone for gfxFontVariation {
-        fn clone(&self) -> Self { *self }
-    }
+    pub type gfxFontVariation = root::mozilla::gfx::FontVariation;
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct gfxFontStyle([u8; 0]);
     pub const kGenericFont_NONE: u8 = 0;
     pub const kGenericFont_moz_variable: u8 = 0;
     pub const kGenericFont_moz_fixed: u8 = 1;
     pub const kGenericFont_serif: u8 = 2;
     pub const kGenericFont_sans_serif: u8 = 4;
@@ -17215,17 +17216,17 @@ pub mod root {
         pub stretch: i16,
         pub kerning: u8,
         pub synthesis: u8,
         pub size: root::nscoord,
         pub sizeAdjust: f32,
         pub alternateValues: root::nsTArray<root::gfxAlternateValue>,
         pub featureValueLookup: root::RefPtr<root::gfxFontFeatureValueSet>,
         pub fontFeatureSettings: root::nsTArray<root::gfxFontFeature>,
-        pub fontVariationSettings: root::nsTArray<root::gfxFontVariation>,
+        pub fontVariationSettings: root::nsTArray<root::mozilla::gfx::FontVariation>,
         pub languageOverride: u32,
     }
     #[test]
     fn bindgen_test_layout_nsFont() {
         assert_eq!(::std::mem::size_of::<nsFont>() , 88usize , concat ! (
                    "Size of: " , stringify ! ( nsFont ) ));
         assert_eq! (::std::mem::align_of::<nsFont>() , 8usize , concat ! (
                     "Alignment of " , stringify ! ( nsFont ) ));
@@ -22850,16 +22851,17 @@ pub mod root {
         pub mFirstProxy: *mut ::std::os::raw::c_void,
         pub mValidator: *mut root::imgCacheValidator,
         pub mRedirectCallback: root::nsCOMPtr<root::nsIAsyncVerifyRedirectCallback>,
         pub mNewRedirectChannel: root::nsCOMPtr<root::nsIChannel>,
         pub mInnerWindowId: u64,
         pub mCORSMode: i32,
         pub mReferrerPolicy: root::imgRequest_ReferrerPolicy,
         pub mImageErrorCode: root::nsresult,
+        pub mBoostCategoriesRequested: u32,
         pub mMutex: root::mozilla::Mutex,
         pub mProgressTracker: root::RefPtr<root::mozilla::image::ProgressTracker>,
         pub mImage: root::RefPtr<root::mozilla::image::Image>,
         pub _bitfield_1: u8,
         pub __bindgen_padding_0: [u8; 7usize],
     }
     pub type imgRequest_Image = root::mozilla::image::Image;
     pub type imgRequest_ImageCacheKey = root::mozilla::image::ImageCacheKey;
@@ -27502,771 +27504,795 @@ pub mod root {
                    root::RefPtr<root::mozilla::StyleSheet> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::StyleSheet>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::StyleSheet> ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_42() {
+        assert_eq!(::std::mem::size_of::<root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>>()
+                   , 24usize , concat ! (
+                   "Size of template specialization: " , stringify ! (
+                   root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>
+                   ) ));
+        assert_eq!(::std::mem::align_of::<root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>>()
+                   , 8usize , concat ! (
+                   "Alignment of template specialization: " , stringify ! (
+                   root::mozilla::LinkedList<root::mozilla::dom::MediaQueryList>
+                   ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_43() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::Element>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::Element> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::Element>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::Element> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_43() {
+    fn __bindgen_test_layout_template_44() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::Element>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::Element>> )
                    ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::Element>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::Element>> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_44() {
+    fn __bindgen_test_layout_template_45() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIObserver>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIObserver> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIObserver>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIObserver> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_45() {
+    fn __bindgen_test_layout_template_46() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::nsCOMPtr<root::nsIObserver>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::nsCOMPtr<root::nsIObserver>> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::nsCOMPtr<root::nsIObserver>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::nsCOMPtr<root::nsIObserver>> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_46() {
+    fn __bindgen_test_layout_template_47() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsIDocument>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIDocument> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsIDocument>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIDocument> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_47() {
+    fn __bindgen_test_layout_template_48() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsContentList>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsContentList> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsContentList>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsContentList> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_48() {
+    fn __bindgen_test_layout_template_49() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsINode>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsINode> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsINode>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsINode> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_49() {
+    fn __bindgen_test_layout_template_50() {
+        assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::mozilla::dom::Link>>()
+                   , 8usize , concat ! (
+                   "Size of template specialization: " , stringify ! (
+                   root::nsCOMPtr<root::mozilla::dom::Link> ) ));
+        assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::mozilla::dom::Link>>()
+                   , 8usize , concat ! (
+                   "Alignment of template specialization: " , stringify ! (
+                   root::nsCOMPtr<root::mozilla::dom::Link> ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_51() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIWeakReference>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIWeakReference> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIWeakReference>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIWeakReference> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_50() {
+    fn __bindgen_test_layout_template_52() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_51() {
+    fn __bindgen_test_layout_template_53() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::nsRect>>() ,
                    8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::nsRect> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::nsRect>>() ,
                    8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::nsRect> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_52() {
+    fn __bindgen_test_layout_template_54() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsBidi>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsBidi> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsBidi>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsBidi> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_53() {
+    fn __bindgen_test_layout_template_55() {
         assert_eq!(::std::mem::size_of::<[u64; 28usize]>() , 224usize , concat
                    ! (
                    "Size of template specialization: " , stringify ! (
                    [u64; 28usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 28usize]>() , 8usize , concat
                    ! (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 28usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_54() {
+    fn __bindgen_test_layout_template_56() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<*mut root::nsIContent>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::nsIContent> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<*mut root::nsIContent>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::nsIContent> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_55() {
+    fn __bindgen_test_layout_template_57() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::mozilla::dom::CSSValue>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::dom::CSSValue> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::mozilla::dom::CSSValue>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::dom::CSSValue> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_56() {
+    fn __bindgen_test_layout_template_58() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::mozilla::dom::TimeoutManager>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_57() {
+    fn __bindgen_test_layout_template_59() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsISupports>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsISupports> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsISupports>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsISupports> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_58() {
+    fn __bindgen_test_layout_template_60() {
         assert_eq!(::std::mem::size_of::<root::nsCOMPtr<root::nsIRunnable>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIRunnable> ) ));
         assert_eq!(::std::mem::align_of::<root::nsCOMPtr<root::nsIRunnable>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsCOMPtr<root::nsIRunnable> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_59() {
+    fn __bindgen_test_layout_template_61() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsIContent>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIContent> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsIContent>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsIContent> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_60() {
+    fn __bindgen_test_layout_template_62() {
         assert_eq!(::std::mem::size_of::<[u64; 5usize]>() , 40usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 5usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 5usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 5usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_61() {
+    fn __bindgen_test_layout_template_63() {
         assert_eq!(::std::mem::size_of::<root::mozilla::OwningNonNull<root::nsINode>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::nsINode> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::OwningNonNull<root::nsINode>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::nsINode> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_62() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
-    fn __bindgen_test_layout_template_63() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_64() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_65() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_66() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_67() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_68() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_68() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_69() {
-        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_70() {
         assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 4usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 4usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_71() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_72() {
+        assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 4usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_73() {
         assert_eq!(::std::mem::size_of::<u32>() , 4usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u32 )
                    ));
         assert_eq!(::std::mem::align_of::<u32>() , 4usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u32 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_72() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
-    fn __bindgen_test_layout_template_73() {
-        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
-                   (
-                   "Size of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
-                   (
-                   "Alignment of template specialization: " , stringify ! (
-                   [u32; 2usize] ) ));
-    }
-    #[test]
     fn __bindgen_test_layout_template_74() {
         assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 2usize] ) ));
     }
     #[test]
     fn __bindgen_test_layout_template_75() {
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_76() {
+        assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat !
+                   (
+                   "Size of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+        assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat !
+                   (
+                   "Alignment of template specialization: " , stringify ! (
+                   [u32; 2usize] ) ));
+    }
+    #[test]
+    fn __bindgen_test_layout_template_77() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<f64>>() , 8usize ,
                    concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<f64> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<f64>>() , 8usize ,
                    concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<f64> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_76() {
+    fn __bindgen_test_layout_template_78() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_77() {
+    fn __bindgen_test_layout_template_79() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::RefPtr<root::mozilla::dom::DOMIntersectionObserverEntry>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_78() {
+    fn __bindgen_test_layout_template_80() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::ProfilerBacktrace,
                                                root::ProfilerBacktraceDestructor>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::ProfilerBacktrace,
                          root::ProfilerBacktraceDestructor>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::ProfilerBacktrace,
                                                 root::ProfilerBacktraceDestructor>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::ProfilerBacktrace,
                          root::ProfilerBacktraceDestructor>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_79() {
+    fn __bindgen_test_layout_template_81() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::FontFamilyName>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FontFamilyName> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::FontFamilyName>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FontFamilyName> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_80() {
+    fn __bindgen_test_layout_template_82() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<::std::os::raw::c_uint>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<::std::os::raw::c_uint> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<::std::os::raw::c_uint>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<::std::os::raw::c_uint> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_81() {
+    fn __bindgen_test_layout_template_83() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::FramePropertyTable_PropertyValue>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_82() {
+    fn __bindgen_test_layout_template_84() {
         assert_eq!(::std::mem::size_of::<root::nsPtrHashKey<root::nsIFrame>>()
                    , 16usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsPtrHashKey<root::nsIFrame> ) ));
         assert_eq!(::std::mem::align_of::<root::nsPtrHashKey<root::nsIFrame>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsPtrHashKey<root::nsIFrame> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_83() {
+    fn __bindgen_test_layout_template_85() {
         assert_eq!(::std::mem::size_of::<[u64; 5usize]>() , 40usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 5usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 5usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 5usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_84() {
+    fn __bindgen_test_layout_template_86() {
         assert_eq!(::std::mem::size_of::<root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::OwningNonNull<root::mozilla::EffectCompositor_AnimationStyleRuleProcessor>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_85() {
+    fn __bindgen_test_layout_template_87() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::ProxyBehaviour>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::ProxyBehaviour> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::ProxyBehaviour>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::ProxyBehaviour> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_86() {
+    fn __bindgen_test_layout_template_88() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::mozilla::URLExtraData>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::URLExtraData> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::mozilla::URLExtraData>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::mozilla::URLExtraData> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_87() {
+    fn __bindgen_test_layout_template_89() {
         assert_eq!(::std::mem::size_of::<root::nsMainThreadPtrHolder<root::nsIURI>>()
                    , 24usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsMainThreadPtrHolder<root::nsIURI> ) ));
         assert_eq!(::std::mem::align_of::<root::nsMainThreadPtrHolder<root::nsIURI>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsMainThreadPtrHolder<root::nsIURI> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_88() {
+    fn __bindgen_test_layout_template_90() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsCSSValueList>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValueList> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsCSSValueList>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValueList> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_89() {
+    fn __bindgen_test_layout_template_91() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsCSSValueList,
                                                root::mozilla::DefaultDelete<root::nsCSSValueList>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValueList,
                          root::mozilla::DefaultDelete<root::nsCSSValueList>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsCSSValueList,
                                                 root::mozilla::DefaultDelete<root::nsCSSValueList>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValueList,
                          root::mozilla::DefaultDelete<root::nsCSSValueList>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_90() {
+    fn __bindgen_test_layout_template_92() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsCSSValuePairList>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValuePairList> )
                    ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsCSSValuePairList>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsCSSValuePairList> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_91() {
+    fn __bindgen_test_layout_template_93() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsCSSValuePairList,
                                                root::mozilla::DefaultDelete<root::nsCSSValuePairList>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValuePairList,
                          root::mozilla::DefaultDelete<root::nsCSSValuePairList>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsCSSValuePairList,
                                                 root::mozilla::DefaultDelete<root::nsCSSValuePairList>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsCSSValuePairList,
                          root::mozilla::DefaultDelete<root::nsCSSValuePairList>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_92() {
+    fn __bindgen_test_layout_template_94() {
         assert_eq!(::std::mem::size_of::<[u64; 2usize]>() , 16usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u64; 2usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 2usize]>() , 8usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 2usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_93() {
+    fn __bindgen_test_layout_template_95() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_94() {
+    fn __bindgen_test_layout_template_96() {
         assert_eq!(::std::mem::size_of::<[u32; 3usize]>() , 12usize , concat !
                    (
                    "Size of template specialization: " , stringify ! (
                    [u32; 3usize] ) ));
         assert_eq!(::std::mem::align_of::<[u32; 3usize]>() , 4usize , concat !
                    (
                    "Alignment of template specialization: " , stringify ! (
                    [u32; 3usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_95() {
+    fn __bindgen_test_layout_template_97() {
         assert_eq!(::std::mem::size_of::<root::already_AddRefed<root::nsStyleImageRequest>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsStyleImageRequest> ) ));
         assert_eq!(::std::mem::align_of::<root::already_AddRefed<root::nsStyleImageRequest>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::already_AddRefed<root::nsStyleImageRequest> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_96() {
+    fn __bindgen_test_layout_template_98() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::nsStyleSides>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsStyleSides> ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::nsStyleSides>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::nsStyleSides> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_97() {
+    fn __bindgen_test_layout_template_99() {
         assert_eq!(::std::mem::size_of::<root::mozilla::UniquePtr<root::nsStyleSides,
                                                root::mozilla::DefaultDelete<root::nsStyleSides>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsStyleSides,
                          root::mozilla::DefaultDelete<root::nsStyleSides>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::UniquePtr<root::nsStyleSides,
                                                 root::mozilla::DefaultDelete<root::nsStyleSides>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::UniquePtr<root::nsStyleSides,
                          root::mozilla::DefaultDelete<root::nsStyleSides>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_98() {
+    fn __bindgen_test_layout_template_100() {
         assert_eq!(::std::mem::size_of::<root::mozilla::DefaultDelete<root::CachedBorderImageData>>()
                    , 1usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::CachedBorderImageData> )
                    ));
         assert_eq!(::std::mem::align_of::<root::mozilla::DefaultDelete<root::CachedBorderImageData>>()
                    , 1usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::DefaultDelete<root::CachedBorderImageData> )
                    ));
     }
     #[test]
-    fn __bindgen_test_layout_template_99() {
+    fn __bindgen_test_layout_template_101() {
         assert_eq!(::std::mem::size_of::<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>()
                    , 32usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr> ) ));
         assert_eq!(::std::mem::align_of::<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_100() {
+    fn __bindgen_test_layout_template_102() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::std::pair<::nsstring::nsStringRepr,
                                                      ::nsstring::nsStringRepr>>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::std::pair<::nsstring::nsStringRepr,
                                                       ::nsstring::nsStringRepr>>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::std::pair<::nsstring::nsStringRepr, ::nsstring::nsStringRepr>>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_101() {
+    fn __bindgen_test_layout_template_103() {
         assert_eq!(::std::mem::size_of::<[u64; 18usize]>() , 144usize , concat
                    ! (
                    "Size of template specialization: " , stringify ! (
                    [u64; 18usize] ) ));
         assert_eq!(::std::mem::align_of::<[u64; 18usize]>() , 8usize , concat
                    ! (
                    "Alignment of template specialization: " , stringify ! (
                    [u64; 18usize] ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_102() {
+    fn __bindgen_test_layout_template_104() {
         assert_eq!(::std::mem::size_of::<root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::mozilla::BaseTimeDuration<root::mozilla::StickyTimeDurationValueCalculator>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_103() {
+    fn __bindgen_test_layout_template_105() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>
                    ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<root::mozilla::DisplayItemClip_RoundedRect>
                    ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_104() {
+    fn __bindgen_test_layout_template_106() {
         assert_eq!(::std::mem::size_of::<root::RefPtr<root::mozilla::dom::DOMRect>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMRect> ) ));
         assert_eq!(::std::mem::align_of::<root::RefPtr<root::mozilla::dom::DOMRect>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::RefPtr<root::mozilla::dom::DOMRect> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_105() {
+    fn __bindgen_test_layout_template_107() {
         assert_eq!(::std::mem::size_of::<u64>() , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! ( u64 )
                    ));
         assert_eq!(::std::mem::align_of::<u64>() , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    u64 ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_106() {
+    fn __bindgen_test_layout_template_108() {
         assert_eq!(::std::mem::size_of::<root::nsTArray<*mut root::mozilla::css::DocumentRule>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::mozilla::css::DocumentRule> ) ));
         assert_eq!(::std::mem::align_of::<root::nsTArray<*mut root::mozilla::css::DocumentRule>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsTArray<*mut root::mozilla::css::DocumentRule> ) ));
     }
     #[test]
-    fn __bindgen_test_layout_template_107() {
+    fn __bindgen_test_layout_template_109() {
         assert_eq!(::std::mem::size_of::<root::nsAutoPtr<root::nsMediaQuery>>()
                    , 8usize , concat ! (
                    "Size of template specialization: " , stringify ! (
                    root::nsAutoPtr<root::nsMediaQuery> ) ));
         assert_eq!(::std::mem::align_of::<root::nsAutoPtr<root::nsMediaQuery>>()
                    , 8usize , concat ! (
                    "Alignment of template specialization: " , stringify ! (
                    root::nsAutoPtr<root::nsMediaQuery> ) ));
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -822,19 +822,23 @@ fn static_assert() {
 <% border_style_keyword = Keyword("border-style",
                                   "none solid double dotted dashed hidden groove ridge inset outset") %>
 
 <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
                                      for x in SIDES
                                      for y in ["color", "style", "width"]] +
                                     ["border-{0}-radius".format(x.ident.replace("_", "-"))
                                      for x in CORNERS]) %>
+
+<% skip_moz_border_color_longhands = " ".join("-moz-border-{0}-colors".format(x.ident)
+                                              for x in SIDES) %>
 <%self:impl_trait style_struct_name="Border"
                   skip_longhands="${skip_border_longhands} border-image-source border-image-outset
-                                  border-image-repeat border-image-width border-image-slice"
+                                  border-image-repeat border-image-width border-image-slice
+                                  ${skip_moz_border_color_longhands}"
                   skip_additionals="*">
 
     % for side in SIDES:
     <% impl_keyword("border_%s_style" % side.ident,
                     "mBorderStyle[%s]" % side.index,
                     border_style_keyword,
                     on_set="update_border_%s" % side.ident,
                     need_clone=True) %>
@@ -875,16 +879,52 @@ fn static_assert() {
                       "mComputedBorder.%s" % side.ident,
                       inherit_from="mBorder.%s" % side.ident,
                       need_clone=True,
                       round_to_pixels=True) %>
 
     pub fn border_${side.ident}_has_nonzero_width(&self) -> bool {
         self.gecko.mComputedBorder.${side.ident} != 0
     }
+
+    #[allow(non_snake_case)]
+    pub fn set__moz_border_${side.ident}_colors(&mut self,
+                                                v: longhands::_moz_border_${side.ident}_colors::computed_value::T) {
+        match v.0 {
+            None => {
+                unsafe {
+                    bindings::Gecko_ClearMozBorderColors(&mut self.gecko,
+                                                         structs::Side::eSide${to_camel_case(side.ident)});
+                }
+            },
+            Some(ref colors) => {
+                unsafe {
+                    bindings::Gecko_EnsureMozBorderColors(&mut self.gecko);
+                    bindings::Gecko_ClearMozBorderColors(&mut self.gecko,
+                                                         structs::Side::eSide${to_camel_case(side.ident)});
+                }
+                for color in colors {
+                    let c = color_to_nscolor_zero_currentcolor(*color);
+                    unsafe {
+                        bindings::Gecko_AppendMozBorderColors(&mut self.gecko,
+                                                              structs::Side::eSide${to_camel_case(side.ident)},
+                                                              c);
+                    }
+                }
+            }
+        }
+    }
+
+    #[allow(non_snake_case)]
+    pub fn copy__moz_border_${side.ident}_colors_from(&mut self, other: &Self) {
+        unsafe {
+            bindings::Gecko_CopyMozBorderColors(&mut self.gecko, &other.gecko,
+                                                structs::Side::eSide${to_camel_case(side.ident)});
+        }
+    }
     % endfor
 
     % for corner in CORNERS:
     <% impl_corner_style_coord("border_%s_radius" % corner.ident,
                                "mBorderRadius",
                                corner.x_index,
                                corner.y_index,
                                need_clone=True) %>
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -68,16 +68,140 @@
     ${helpers.predefined_type("border-" + corner + "-radius", "BorderRadiusSize",
                               "computed::BorderRadiusSize::zero()",
                               "parse", extra_prefixes="webkit",
                               spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner,
                               boxed=True,
                               animation_value_type="ComputedValue")}
 % endfor
 
+/// -moz-border-*-colors: color, string, enum, none, inherit/initial
+/// These non-spec properties are just for Gecko (Stylo) internal use.
+% for side in PHYSICAL_SIDES:
+    <%helpers:longhand name="-moz-border-${side}-colors" animation_value_type="none"
+                       spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-*-colors)"
+                       products="gecko">
+        use std::fmt;
+        use style_traits::ToCss;
+        use values::HasViewportPercentage;
+        use values::specified::CSSColor;
+        no_viewport_percentage!(SpecifiedValue);
+
+        pub mod computed_value {
+            use values::computed::CSSColor;
+            #[derive(Debug, Clone, PartialEq)]
+            #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+            pub struct T(pub Option<Vec<CSSColor>>);
+        }
+
+        #[derive(Debug, Clone, PartialEq)]
+        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+        pub enum SpecifiedValue {
+            None,
+            Colors(Vec<CSSColor>),
+        }
+
+        impl ToCss for computed_value::T {
+            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+                match self.0 {
+                    None => return dest.write_str("none"),
+                    Some(ref vec) => {
+                        let mut first = true;
+                        for ref color in vec {
+                            if !first {
+                                try!(dest.write_str(" "));
+                            }
+                            first = false;
+                            try!(color.to_css(dest))
+                        }
+                        Ok(())
+                    }
+                }
+            }
+        }
+
+        impl ToCss for SpecifiedValue {
+            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+                match *self {
+                    SpecifiedValue::None => return dest.write_str("none"),
+                    SpecifiedValue::Colors(ref vec) => {
+                        let mut first = true;
+                        for ref color in vec {
+                            if !first {
+                                try!(dest.write_str(" "));
+                            }
+                            first = false;
+                            try!(color.to_css(dest))
+                        }
+                        Ok(())
+                    }
+                }
+            }
+        }
+
+        #[inline] pub fn get_initial_value() -> computed_value::T {
+            computed_value::T(None)
+        }
+
+        #[inline] pub fn get_initial_specified_value() -> SpecifiedValue {
+            SpecifiedValue::None
+        }
+
+        impl ToComputedValue for SpecifiedValue {
+            type ComputedValue = computed_value::T;
+
+            #[inline]
+            fn to_computed_value(&self, context: &Context) -> computed_value::T {
+                match *self {
+                    SpecifiedValue::Colors(ref vec) => {
+                        computed_value::T(Some(vec.iter()
+                                                  .map(|c| c.to_computed_value(context))
+                                                  .collect()))
+                    },
+                    SpecifiedValue::None => {
+                        computed_value::T(None)
+                    }
+                }
+            }
+            #[inline]
+            fn from_computed_value(computed: &computed_value::T) -> Self {
+                match *computed {
+                    computed_value::T(Some(ref vec)) => {
+                        SpecifiedValue::Colors(vec.iter()
+                                                  .map(|c| ToComputedValue::from_computed_value((c)))
+                                                  .collect())
+                    },
+                    computed_value::T(None) => {
+                        SpecifiedValue::None
+                    }
+                }
+            }
+        }
+
+        #[inline]
+        pub fn parse(context: &ParserContext, input: &mut Parser)
+                     -> Result<SpecifiedValue, ()> {
+            if input.try(|input| input.expect_ident_matching("none")).is_ok() {
+                return Ok(SpecifiedValue::None)
+            }
+
+            let mut result = Vec::new();
+            while let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
+                result.push(value);
+            }
+
+            if !result.is_empty() {
+                Ok(SpecifiedValue::Colors(result))
+            } else {
+                Err(())
+            }
+        }
+    </%helpers:longhand>
+% endfor
+
 ${helpers.single_keyword("box-decoration-break", "slice clone",
                          gecko_enum_prefix="StyleBoxDecorationBreak",
                          gecko_inexhaustive=True,
                          spec="https://drafts.csswg.org/css-break/#propdef-box-decoration-break",
                          products="gecko", animation_value_type="none")}
 
 ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
                          gecko_ffi_name="mFloatEdge",
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -836,17 +836,17 @@ impl PropertyId {
     /// Returns Err(()) for unknown non-custom properties
     pub fn parse(property_name: Cow<str>) -> Result<Self, ()> {
         if let Ok(name) = ::custom_properties::parse_name(&property_name) {
             return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
         }
 
         // FIXME(https://github.com/rust-lang/rust/issues/33156): remove this enum and use PropertyId
         // when stable Rust allows destructors in statics.
-        enum StaticId {
+        pub enum StaticId {
             Longhand(LonghandId),
             Shorthand(ShorthandId),
         }
         ascii_case_insensitive_phf_map! {
             static_id -> StaticId = {
                 % for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
                     % for property in properties:
                         % for name in [property.name] + property.alias:
--- a/servo/components/style/properties/shorthand/border.mako.rs
+++ b/servo/components/style/properties/shorthand/border.mako.rs
@@ -9,34 +9,34 @@
                                spec="https://drafts.csswg.org/css-backgrounds/#border-color")}
 
 ${helpers.four_sides_shorthand("border-style", "border-%s-style",
                                "specified::BorderStyle::parse",
                                spec="https://drafts.csswg.org/css-backgrounds/#border-style")}
 
 <%helpers:shorthand name="border-width" sub_properties="${
         ' '.join('border-%s-width' % side
-                 for side in ['top', 'right', 'bottom', 'left'])}"
+                 for side in PHYSICAL_SIDES)}"
     spec="https://drafts.csswg.org/css-backgrounds/#border-width">
     use super::parse_four_sides;
     use parser::Parse;
     use values::specified;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let (top, right, bottom, left) = try!(parse_four_sides(input, |i| specified::BorderWidth::parse(context, i)));
         Ok(Longhands {
-            % for side in ["top", "right", "bottom", "left"]:
+            % for side in PHYSICAL_SIDES:
                 ${to_rust_ident('border-%s-width' % side)}: ${side},
             % endfor
         })
     }
 
     impl<'a> ToCss for LonghandsToSerialize<'a>  {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            % for side in ["top", "right", "bottom", "left"]:
+            % for side in PHYSICAL_SIDES:
                 let ${side} = self.border_${side}_width.clone();
             % endfor
 
             super::serialize_four_sides(dest, &top, &right, &bottom, &left)
         }
     }
 </%helpers:shorthand>
 
@@ -119,32 +119,42 @@ pub fn parse_border(context: &ParserCont
         }
     }
 
     </%helpers:shorthand>
 % endfor
 
 <%helpers:shorthand name="border"
     sub_properties="${' '.join('border-%s-%s' % (side, prop)
-        for side in ['top', 'right', 'bottom', 'left']
+        for side in PHYSICAL_SIDES
         for prop in ['color', 'style', 'width'])}
         ${' '.join('border-image-%s' % name
-        for name in ['outset', 'repeat', 'slice', 'source', 'width'])}"
+        for name in ['outset', 'repeat', 'slice', 'source', 'width'])}
+        ${' '.join('-moz-border-%s-colors' % side
+        for side in PHYSICAL_SIDES) if product == 'gecko' else ''}"
     spec="https://drafts.csswg.org/css-backgrounds/#border">
 
+    % if product == "gecko":
+        use properties::longhands::{_moz_border_top_colors, _moz_border_right_colors,
+                                    _moz_border_bottom_colors, _moz_border_left_colors};
+    % endif
+
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
         use properties::longhands::{border_image_source, border_image_width};
 
         let (color, style, width) = try!(super::parse_border(context, input));
         Ok(Longhands {
-            % for side in ["top", "right", "bottom", "left"]:
+            % for side in PHYSICAL_SIDES:
                 border_${side}_color: color.clone(),
                 border_${side}_style: style,
                 border_${side}_width: width.clone(),
+                % if product == "gecko":
+                    _moz_border_${side}_colors: _moz_border_${side}_colors::get_initial_specified_value(),
+                % endif
             % endfor
 
             // The ‘border’ shorthand resets ‘border-image’ to its initial value.
             // See https://drafts.csswg.org/css-backgrounds-3/#the-border-shorthands
             % for name in "outset repeat slice source width".split():
                 border_image_${name}: border_image_${name}::get_initial_specified_value(),
             % endfor
         })
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -1155,18 +1155,22 @@ impl LengthOrPercentage {
     fn parse_internal(context: &ParserContext, input: &mut Parser, num_context: AllowedLengthType)
                       -> Result<LengthOrPercentage, ()>
     {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
                 NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length),
             Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
-            Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentage::zero()),
+            Token::Number(ref value) => {
+                if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() {
+                    return Err(())
+                }
+                Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
+            }
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(|i| {
                     CalcLengthOrPercentage::parse_length_or_percentage(context, i)
                 }));
                 Ok(LengthOrPercentage::Calc(Box::new(calc)))
             },
             _ => Err(())
         }
@@ -1279,18 +1283,24 @@ impl ToCss for LengthOrPercentageOrAuto 
 impl LengthOrPercentageOrAuto {
     fn parse_internal(context: &ParserContext, input: &mut Parser, num_context: AllowedLengthType)
                       -> Result<Self, ()> {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
                 NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length),
             Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentageOrAuto::Percentage(Percentage(value.unit_value))),
-            Token::Number(ref value) if value.value == 0. =>
-                Ok(Self::zero()),
+            Token::Number(ref value) if value.value == 0. => {
+                if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() {
+                    return Err(())
+                }
+                Ok(LengthOrPercentageOrAuto::Length(
+                    NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
+                ))
+            }
             Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
                 Ok(LengthOrPercentageOrAuto::Auto),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(|i| {
                     CalcLengthOrPercentage::parse_length_or_percentage(context, i)
                 }));
                 Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
             },
@@ -1358,18 +1368,24 @@ impl LengthOrPercentageOrNone {
     fn parse_internal(context: &ParserContext, input: &mut Parser, num_context: AllowedLengthType)
                       -> Result<LengthOrPercentageOrNone, ()>
     {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
                 NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length),
             Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))),
-            Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentageOrNone::Length(NoCalcLength::zero())),
+            Token::Number(ref value) if value.value == 0. => {
+                if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() {
+                    return Err(())
+                }
+                Ok(LengthOrPercentageOrNone::Length(
+                    NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
+                ))
+            }
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(|i| {
                     CalcLengthOrPercentage::parse_length_or_percentage(context, i)
                 }));
                 Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
             },
             Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
                 Ok(LengthOrPercentageOrNone::None),
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -10,14 +10,14 @@ name = "style_traits"
 path = "lib.rs"
 
 [features]
 servo = ["heapsize", "heapsize_derive", "serde", "serde_derive",
          "cssparser/heapsize", "cssparser/serde"]
 
 [dependencies]
 app_units = "0.4"
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 heapsize = {version = "0.3.0", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 serde = {version = "0.9", optional = true}
 serde_derive = {version = "0.9", optional = true}
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -11,17 +11,17 @@ crate-type = ["staticlib", "rlib"]
 
 [features]
 bindgen = ["style/use_bindgen"]
 testing = ["style/testing"]
 gecko_debug = ["style/gecko_debug"]
 
 [dependencies]
 atomic_refcell = "0.1"
-cssparser = "0.12.1"
+cssparser = "0.13"
 env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 parking_lot = "0.3"
 selectors = {path = "../../components/selectors"}
 style = {path = "../../components/style", features = ["gecko"]}
 style_traits = {path = "../../components/style_traits"}
 
--- a/servo/ports/glutin/window.rs
+++ b/servo/ports/glutin/window.rs
@@ -688,16 +688,17 @@ impl Window {
             listener: *mut (NestedEventLoopListener + 'static)) {
         G_NESTED_EVENT_LOOP_LISTENER = Some(listener)
     }
 
     pub unsafe fn remove_nested_event_loop_listener(&self) {
         G_NESTED_EVENT_LOOP_LISTENER = None
     }
 
+    #[cfg(target_os = "windows")]
     fn char_to_script_key(c: char) -> Option<constellation_msg::Key> {
         match c {
             ' ' => Some(Key::Space),
             '"' => Some(Key::Apostrophe),
             '\'' => Some(Key::Apostrophe),
             '<' => Some(Key::Comma),
             ',' => Some(Key::Comma),
             '_' => Some(Key::Minus),
--- a/servo/ports/servo/main.rs
+++ b/servo/ports/servo/main.rs
@@ -28,16 +28,17 @@ extern crate log;
 extern crate servo;
 #[cfg(not(target_os = "android"))]
 #[macro_use]
 extern crate sig;
 
 use backtrace::Backtrace;
 use servo::Browser;
 use servo::compositing::windowing::WindowEvent;
+#[cfg(target_os = "android")]
 use servo::config;
 use servo::config::opts::{self, ArgumentParsingResult};
 use servo::config::servo_version;
 use std::env;
 use std::panic;
 use std::process;
 use std::rc::Rc;
 use std::thread;
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -9,17 +9,17 @@ name = "style_tests"
 path = "lib.rs"
 doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 app_units = "0.4"
-cssparser = "0.12.1"
+cssparser = "0.13"
 euclid = "0.11"
 html5ever-atoms = "0.3"
 parking_lot = "0.3"
 rayon = "0.6"
 rustc-serialize = "0.3"
 selectors = {path = "../../../components/selectors"}
 servo_atoms = {path = "../../../components/atoms"}
 servo_config = {path = "../../../components/config"}
--- a/servo/tests/unit/stylo/Cargo.toml
+++ b/servo/tests/unit/stylo/Cargo.toml
@@ -11,17 +11,17 @@ name = "stylo_tests"
 path = "lib.rs"
 doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 atomic_refcell = "0.1"
-cssparser = "0.12.1"
+cssparser = "0.13"
 env_logger = "0.4"
 euclid = "0.11"
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 parking_lot = "0.3"
 selectors = {path = "../../../components/selectors"}
 style_traits = {path = "../../../components/style_traits"}
 geckoservo = {path = "../../../ports/geckolib"}
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -1342,22 +1342,22 @@ talos-tp5o:
                     - talos/linux_config.py
                     - remove_executables.py
         extra-options:
             - --suite=tp5o
 
 talos-perf-reftest:
     description: "Talos perf-reftest"
     suite: talos
-    talos-try-name: perfref
+    talos-try-name: perf-reftest
     treeherder-symbol: tc-T(p)
     run-on-projects:
         by-test-platform:
-            linux64-stylo/.*: ['try']
-            default: ['try']
+            linux64-stylo/.*: ['mozilla-central', 'try']
+            default: ['mozilla-central', 'mozilla-inbound', 'autoland', 'try']
     max-run-time: 3600
     mozharness:
         script: talos_script.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 default:
                     - talos/linux_config.py
--- a/taskcluster/scripts/builder/hazard-analysis.sh
+++ b/taskcluster/scripts/builder/hazard-analysis.sh
@@ -146,16 +146,16 @@ function check_hazards () {
     echo "TinderboxPrint: heap write hazards<br/>$NUM_WRITE_HAZARDS"
 
     if [ $NUM_HAZARDS -gt 0 ]; then
         echo "TEST-UNEXPECTED-FAIL $NUM_HAZARDS rooting hazards detected" >&2
         echo "TinderboxPrint: documentation<br/><a href='https://wiki.mozilla.org/Javascript:Hazard_Builds#Diagnosing_a_rooting_hazards_failure'>static rooting hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"
         exit 1
     fi
 
-    NUM_ALLOWED_WRITE_HAZARDS=3
+    NUM_ALLOWED_WRITE_HAZARDS=7
     if [ $NUM_WRITE_HAZARDS -gt $NUM_ALLOWED_WRITE_HAZARDS ]; then
         echo "TEST-UNEXPECTED-FAIL $NUM_WRITE_HAZARDS heap write hazards detected out of $NUM_ALLOWED_WRITE_HAZARDS allowed" >&2
         echo "TinderboxPrint: documentation<br/><a href='https://wiki.mozilla.org/Javascript:Hazard_Builds#Diagnosing_a_heap_write_hazard_failure'>heap write hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"
         exit 1
     fi
     )
 }
--- a/third_party/rust/cssparser-macros/.cargo-checksum.json
+++ b/third_party/rust/cssparser-macros/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"e740a473ab5e2339d639a86f1996b1ecc72f25b25f23b2789c836bff1455cf5a","lib.rs":"2b54cf96da2049eb03e4b30a223124e7f5a9c067975d54ec0ecf92f0245777a1"},"package":"b8f0415de0bdbce823c0db204e00a62c8240fa2d3e04cd13ff7c6396e4446b95"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"3080a72e897022e23ede1dd38cf28049e74a077518cc25d91f559c3b575aa3e3","lib.rs":"17331a3a0b0be3c05fe360e08538baf26b343ae61feec9062429a34a1c1eb1e2"},"package":"079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"}
\ No newline at end of file
--- a/third_party/rust/cssparser-macros/Cargo.toml
+++ b/third_party/rust/cssparser-macros/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "cssparser-macros"
-version = "0.2.0"
+version = "0.3.0"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 description = "Procedural macros for cssparser"
 documentation = "https://docs.rs/cssparser-macros/"
 repository = "https://github.com/servo/rust-cssparser"
 license = "MPL-2.0"
 
 [lib]
 path = "lib.rs"
--- a/third_party/rust/cssparser-macros/lib.rs
+++ b/third_party/rust/cssparser-macros/lib.rs
@@ -22,25 +22,17 @@ define_proc_macros! {
         let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
         let arms = match expr {
             syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
             _ => panic!("expected a match expression, got {:?}", expr)
         };
         max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
             let expr = match *pattern {
                 syn::Pat::Lit(ref expr) => expr,
-                syn::Pat::Wild |
-                syn::Pat::Ident(_, _, None) => return None,
-                syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
-                    match **sub_pattern {
-                        syn::Pat::Lit(ref expr) => expr,
-                        syn::Pat::Wild => return None,
-                        _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
-                    }
-                }
+                syn::Pat::Wild => return None,
                 _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
             };
             match **expr {
                 syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
                     assert_eq!(*string, string.to_ascii_lowercase(),
                                "string patterns must be given in ASCII lowercase");
                     Some(string.len())
                 }
@@ -57,17 +49,17 @@ define_proc_macros! {
         max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
     }
 
     /// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
     /// following TTs are grouped in pairs, each pair being a key as a string literal
     /// and the corresponding value as a const expression.
     ///
     /// Output: a rust-phf map, with keys ASCII-lowercased:
-    /// ```
+    /// ```text
     /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
     /// ```
     #[allow(non_snake_case)]
     pub fn cssparser_internal__phf_map(input: &str) -> String {
         let token_trees = syn::parse_token_trees(input).unwrap();
         let value_type = &token_trees[0];
         let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
             let key = string_literal(&chunk[0]);
--- a/third_party/rust/cssparser/.cargo-checksum.json
+++ b/third_party/rust/cssparser/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"e32812a8f09b0c5b0b972e2e090f8929eb5b600a37ca7aac2ed07ba10c30291e",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"410baf41d446e2e281eabe0c52a0b094b457dbb5d7c096fcfbd6ce4e5e01b998","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"950bcc47a196f07f99f59637c28cc65e02a885130011f90a2b2608248b4724a2","build/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"09249793df09c51ce0f2a8eabae85405cfdbd8c23330bb121f8b61665df853fd","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"5104348cc58a10d113ad4c20f05bdba846ecb4920ee606203fe5d28a6a9f0a13","src/css-parsing-tests/color3_hsl.json":"88936185b3ead36f8613372bf595024073d7787adbf659a62446789a2504b59f","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"dda7244eb3a4fcf6d296762e285f7031028837d987065a09e584e8d973edc7f3","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"6297d9fb7b23875ccf99111a56a8e971a37c4206d7d6782001e95a7194fa6182","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"90a0348cb785f8761d956458880486136de75f2c7ce44ec66da233f73d9098bf","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"ccc0f04541147d4fb90d3fe70591bacfb0c7030706c9be8fa60b80533e522bbc","src/macros.rs":"bd492479eee8c65850bdfc2c9de100eddc224e5d6629cd583219058901cd0ca7","src/nth.rs":"0a5e68bd8a597403e184ebf34e69230ae1e955f92b16b99b3f67cf8730a180a9","src/parser.rs":"a41b1d885389d34b4d81176f844ae3c4100e621628dd50d7348c42b08cdd13ae","src/rules_and_declarations.rs":"6b66a986e411a56998546ab0e64de5285df3368d7c4018c7230a1b6cf6bcc532","src/serializer.rs":"480043750508944fb75295d8638b6b33665273a2ac5791ec8261ae1fe63c0fcd","src/tests.rs":"80e4fec507258fe4e63a590f842f3213b44418cd69d755f78f938894966037db","src/tokenizer.rs":"945c29ff9f4a79d58aee956e27c8b476068859d878ead7c7fed83a9e89d2159f","src/unicode_range.rs":"fa0198eb00a68cd71d009551194a3f6d2cb0501513b77d9ea2fea22bfa45c141"},"package":"fb067f9d88368ca9053aea00581556151ef96f2591e32ad44f3312d7e6b67392"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"0b944a5f5edfe3dca4796907e63f537a0e919630df66dca7945d51ba4e3c8051",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"a6a5eab45b7398c4930ad529f4bf3f77b70fd4a3ea8c82fff5bb93ae305eacf9","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"950bcc47a196f07f99f59637c28cc65e02a885130011f90a2b2608248b4724a2","build/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"0751c51a39a2d5d03dd5c41405bafc791eb12b508b7347d3a48ebddd97b67ba3","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"6a09e71e7095374a6b44b9cb4341b7f675afe66a93427c62a9a0ff5f8c20ac6f","src/css-parsing-tests/color3_hsl.json":"88936185b3ead36f8613372bf595024073d7787adbf659a62446789a2504b59f","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"dda7244eb3a4fcf6d296762e285f7031028837d987065a09e584e8d973edc7f3","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"d7c3533f5f7158da10fa5c34ae5e1bd2b3b0da5d2ca90c16b6cd76f310f22941","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"62720b143ddf52508baad42921473dd69519aad6c1cd49f37f3f264dc29e1c13","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"ccc0f04541147d4fb90d3fe70591bacfb0c7030706c9be8fa60b80533e522bbc","src/macros.rs":"adb9773c157890381556ea83d7942dcc676f99eea71abbb6afeffee1e3f28960","src/nth.rs":"0a5e68bd8a597403e184ebf34e69230ae1e955f92b16b99b3f67cf8730a180a9","src/parser.rs":"a41b1d885389d34b4d81176f844ae3c4100e621628dd50d7348c42b08cdd13ae","src/rules_and_declarations.rs":"6b66a986e411a56998546ab0e64de5285df3368d7c4018c7230a1b6cf6bcc532","src/serializer.rs":"480043750508944fb75295d8638b6b33665273a2ac5791ec8261ae1fe63c0fcd","src/tests.rs":"80e4fec507258fe4e63a590f842f3213b44418cd69d755f78f938894966037db","src/tokenizer.rs":"945c29ff9f4a79d58aee956e27c8b476068859d878ead7c7fed83a9e89d2159f","src/unicode_range.rs":"f1f1dee3cc4efb6647557c6166aa5a93354fc0ee9beba53c1d63427beffe5a8d"},"package":"b39404c5e04492194e3c69f1a10964b980f2c95c884a940f7903446779f6b027"}
\ No newline at end of file
--- a/third_party/rust/cssparser/.gitignore
+++ b/third_party/rust/cssparser/.gitignore
@@ -1,3 +1,3 @@
-/target
+target
 /Cargo.lock
 /.cargo/config
--- a/third_party/rust/cssparser/Cargo.toml
+++ b/third_party/rust/cssparser/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
 
 name = "cssparser"
-version = "0.12.2"
+version = "0.13.1"
 authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]
 
 description = "Rust implementation of CSS Syntax Level 3"
 documentation = "https://docs.rs/cssparser/"
 repository = "https://github.com/servo/rust-cssparser"
 readme = "README.md"
 keywords = ["css", "syntax", "parser"]
 license = "MPL-2.0"
@@ -15,17 +15,17 @@ build = "build.rs"
 exclude = ["src/css-parsing-tests"]
 
 [dev-dependencies]
 rustc-serialize = "0.3"
 difference = "1.0"
 encoding_rs = "0.5"
 
 [dependencies]
-cssparser-macros = {path = "./macros", version = "0.2"}
+cssparser-macros = {path = "./macros", version = "0.3"}
 heapsize = {version = "0.3", optional = true}
 matches = "0.1"
 phf = "0.7"
 procedural-masquerade = {path = "./procedural-masquerade", version = "0.1"}
 serde = {version = "0.9", optional = true}
 
 [build-dependencies]
 syn = "0.11"
--- a/third_party/rust/cssparser/src/color.rs
+++ b/third_party/rust/cssparser/src/color.rs
@@ -1,13 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use std::cmp;
 use std::fmt;
 use std::f32::consts::PI;
 
 use super::{Token, Parser, ToCss};
 use tokenizer::NumericValue;
 
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -26,17 +25,22 @@ pub struct RGBA {
 }
 
 impl RGBA {
     /// Constructs a new RGBA value from float components. It expects the red,
     /// green, blue and alpha channels in that order, and all values will be
     /// clamped to the 0.0 ... 1.0 range.
     #[inline]
     pub fn from_floats(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
-        Self::new(clamp_f32(red), clamp_f32(green), clamp_f32(blue), clamp_f32(alpha))
+        Self::new(
+            clamp_unit_f32(red),
+            clamp_unit_f32(green),
+            clamp_unit_f32(blue),
+            clamp_unit_f32(alpha),
+        )
     }
 
     /// Returns a transparent color.
     #[inline]
     pub fn transparent() -> Self {
         Self::new(0, 0, 0, 0)
     }
 
@@ -94,17 +98,17 @@ impl Deserialize for RGBA {
 known_heap_size!(0, RGBA);
 
 impl ToCss for RGBA {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result
         where W: fmt::Write,
     {
         // Try first with two decimal places, then with three.
         let mut rounded_alpha = (self.alpha_f32() * 100.).round() / 100.;
-        if clamp_f32(rounded_alpha) != self.alpha {
+        if clamp_unit_f32(rounded_alpha) != self.alpha {
             rounded_alpha = (self.alpha_f32() * 1000.).round() / 1000.;
         }
 
         if self.alpha == 255 {
             write!(dest, "rgb({}, {}, {})", self.red, self.green, self.blue)
         } else {
             write!(dest, "rgba({}, {}, {}, {})",
                    self.red, self.green, self.blue, rounded_alpha)
@@ -376,62 +380,55 @@ fn parse_color_hash(value: &str) -> Resu
             try!(from_hex(value[0])) * 17,
             try!(from_hex(value[1])) * 17,
             try!(from_hex(value[2])) * 17,
         ),
         _ => Err(())
     }
 }
 
-
-fn clamp_i32(val: i32) -> u8 {
-    cmp::min(cmp::max(0, val), 255) as u8
-}
-
-fn clamp_f32(val: f32) -> u8 {
+fn clamp_unit_f32(val: f32) -> u8 {
     // Scale by 256, not 255, so that each of the 256 u8 values has an equal range
     // of f32 values mapping to it. Floor before clamping.
     //
     // Clamping to 256 and flooring after would let 1.0 map to 256, and
     // `256.0_f32 as u8` is undefined behavior:
     //
     // https://github.com/rust-lang/rust/issues/10184
-    (val * 256.).floor().max(0.).min(255.) as u8
+    clamp_256_f32(val * 256.)
+}
+
+fn clamp_256_f32(val: f32) -> u8 {
+    val.floor().max(0.).min(255.) as u8
 }
 
 #[inline]
 fn parse_color_function(name: &str, arguments: &mut Parser) -> Result<Color, ()> {
-    let is_rgb = match_ignore_ascii_case! { name,
-        "rgb" | "rgba" => true,
-        "hsl" | "hsla" => false,
+    let (red, green, blue, uses_commas) = match_ignore_ascii_case! { name,
+        "rgb" | "rgba" => parse_rgb_components_rgb(arguments)?,
+        "hsl" | "hsla" => parse_rgb_components_hsl(arguments)?,
         _ => return Err(())
     };
 
-    let (red, green, blue, uses_commas) = if is_rgb {
-        parse_rgb_components_rgb(arguments)?
-    } else {
-        parse_rgb_components_hsl(arguments)?
-    };
-
     let alpha = if !arguments.is_exhausted() {
         if uses_commas {
             try!(arguments.expect_comma());
         } else {
             match try!(arguments.next()) {
                 Token::Delim('/') => {},
                 _ => return Err(())
             };
         };
         let token = try!(arguments.next());
         match token {
             Token::Number(NumericValue { value: v, .. }) => {
-                clamp_f32(v)
+                clamp_unit_f32(v)
             }
             Token::Percentage(ref v) => {
-                clamp_f32(v.unit_value)
+                clamp_unit_f32(v.unit_value)
             }
             _ => {
                 return Err(())
             }
         }
     } else {
         255
     };
@@ -447,44 +444,44 @@ fn parse_rgb_components_rgb(arguments: &
     let green: u8;
     let blue: u8;
     let mut uses_commas = false;
 
     // Either integers or percentages, but all the same type.
     // https://drafts.csswg.org/css-color/#rgb-functions
     match try!(arguments.next()) {
         Token::Number(NumericValue { value: v, .. }) => {
-            red = clamp_i32(v as i32);
-            green = clamp_i32(match try!(arguments.next()) {
+            red = clamp_256_f32(v);
+            green = clamp_256_f32(match try!(arguments.next()) {
                 Token::Number(NumericValue { value: v, .. }) => v,
                 Token::Comma => {
                     uses_commas = true;
                     try!(arguments.expect_number())
                 }
                 _ => return Err(())
-            } as i32);
+            });
             if uses_commas {
                 try!(arguments.expect_comma());
             }
-            blue = clamp_i32(try!(arguments.expect_number()) as i32);
+            blue = clamp_256_f32(try!(arguments.expect_number()));
         }
         Token::Percentage(ref v) => {
-            red = clamp_f32(v.unit_value);
-            green = clamp_f32(match try!(arguments.next()) {
+            red = clamp_unit_f32(v.unit_value);
+            green = clamp_unit_f32(match try!(arguments.next()) {
                 Token::Percentage(ref v) => v.unit_value,
                 Token::Comma => {
                     uses_commas = true;
                     try!(arguments.expect_percentage())
                 }
                 _ => return Err(())
             });
             if uses_commas {
                 try!(arguments.expect_comma());
             }
-            blue = clamp_f32(try!(arguments.expect_percentage()));
+            blue = clamp_unit_f32(try!(arguments.expect_percentage()));
         }
         _ => return Err(())
     };
     return Ok((red, green, blue, uses_commas));
 }
 
 #[inline]
 fn parse_rgb_components_hsl(arguments: &mut Parser) -> Result<(u8, u8, u8, bool), ()> {
@@ -537,13 +534,13 @@ fn parse_rgb_components_hsl(arguments: &
         else if h3 * 2. < 3. { m2 }
         else if h3 < 2. { m1 + (m2 - m1) * (2. - h3) * 2. }
         else { m1 }
     }
     let m2 = if lightness <= 0.5 { lightness * (saturation + 1.) }
              else { lightness + saturation - lightness * saturation };
     let m1 = lightness * 2. - m2;
     let hue_times_3 = hue * 3.;
-    let red = clamp_f32(hue_to_rgb(m1, m2, hue_times_3 + 1.));
-    let green = clamp_f32(hue_to_rgb(m1, m2, hue_times_3));
-    let blue = clamp_f32(hue_to_rgb(m1, m2, hue_times_3 - 1.));
+    let red = clamp_unit_f32(hue_to_rgb(m1, m2, hue_times_3 + 1.));
+    let green = clamp_unit_f32(hue_to_rgb(m1, m2, hue_times_3));
+    let blue = clamp_unit_f32(hue_to_rgb(m1, m2, hue_times_3 - 1.));
     return Ok((red, green, blue, uses_commas));
 }
--- a/third_party/rust/cssparser/src/css-parsing-tests/color3.json
+++ b/third_party/rust/cssparser/src/css-parsing-tests/color3.json
@@ -248,10 +248,13 @@
 "hsla(133.33333333grad, 75%, 50%, 0.6)", [32, 224, 32, 153],
 "hsla(2.0943951024rad, 75%, 50%, 0.8)", [32, 224, 32, 204],
 "hsla(0.3333333333turn, 75%, 50%, 1.0)", [32, 224, 32, 255],
 "hsl(600deg, 75%, 50%)", [32, 32, 224, 255],
 "hsl(1066.66666666grad, 75%, 50%)", [32, 32, 224, 255],
 "hsl(10.4719755118rad, 75%, 50%)", [32, 32, 224, 255],
 "hsl(2.6666666666turn, 75%, 50%)", [32, 32, 224, 255],
 
+"rgb(-2147483649, 4294967298, -18446744073709551619) /* https://github.com/w3c/web-platform-tests/blob/master/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html */",
+[0, 255, 0, 255],
+
 "cmyk(0, 0, 0, 0)", null
 ]
--- a/third_party/rust/cssparser/src/css-parsing-tests/make_color3_hsl.py
+++ b/third_party/rust/cssparser/src/css-parsing-tests/make_color3_hsl.py
@@ -1,19 +1,33 @@
 import colorsys  # It turns out Python already does HSL -> RGB!
 trim = lambda s: s if not s.endswith('.0') else s[:-2]
 print('[')
 print(',\n'.join(
-    f[0] % (
-        (n, h, trim(str(s/10.)), trim(str(l/10.)),
-         f[1] % round(a / 255., 2) if a is not None else '')
-        + tuple(trim(str(min(255, v * 256)))
-                for v in colorsys.hls_to_rgb(h/360., l/1000., s/1000.))
-        + (a if a is not None else 255,)
+    function_format % tuple(
+        [
+            function_name,
+            hue,
+            trim(str(saturation / 10.)),
+            trim(str(lightness / 10.)),
+            alpha_format % round(alpha / 255., 2) if alpha is not None else ''
+        ] + [
+            trim(str(min(255, component * 256)))
+            for component in colorsys.hls_to_rgb(
+                hue / 360.,
+                lightness / 1000.,
+                saturation / 1000.
+            )
+        ] + [
+            alpha if alpha is not None else 255
+        ]
     )
-    for f in [('"%s(%s, %s%%, %s%%%s)", [%s, %s, %s, %s]', ', %s'), ('"%s(%s %s%% %s%%%s)", [%s, %s, %s, %s]', ' / %s')]
-    for n in ["hsl", "hsla"]
-    for a in [None, 255, 64, 0]
-    for l in range(0, 1001, 125)
-    for s in range(0, 1001, 125)
-    for h in range(0, 360, 30)
+    for function_format, alpha_format in [
+        ('"%s(%s, %s%%, %s%%%s)", [%s, %s, %s, %s]', ', %s'),
+        ('"%s(%s %s%% %s%%%s)", [%s, %s, %s, %s]', ' / %s')
+    ]
+    for function_name in ["hsl", "hsla"]
+    for alpha in [None, 255, 64, 0]
+    for lightness in range(0, 1001, 125)
+    for saturation in range(0, 1001, 125)
+    for hue in range(0, 360, 30)
 ))
 print(']')
--- a/third_party/rust/cssparser/src/css-parsing-tests/urange.json
+++ b/third_party/rust/cssparser/src/css-parsing-tests/urange.json
@@ -55,16 +55,20 @@
     null
 ],
 
 "U+2 , U+???", [
     [2, 2],
     [0, 4095]
 ],
 
+"U+4E-9F", [
+    [78, 159]
+],
+
 "u+20-3F, u+3F-3F, u+3F-3E, U+0-110000, U+0-10FFFF, U+100000-2, U+1000000-2, U+10-200000", [
     [32, 63],
     [63, 63],
     null,
     null,
     [0, 1114111],
     null,
     null,
--- a/third_party/rust/cssparser/src/macros.rs
+++ b/third_party/rust/cssparser/src/macros.rs
@@ -17,17 +17,17 @@ define_invoke_proc_macro!(cssparser_inte
 ///
 /// # fn main() {}  // Make doctest not wrap everythig in its own main
 /// # fn dummy(function_name: &String) { let _ =
 /// match_ignore_ascii_case! { &function_name,
 ///     "rgb" => parse_rgb(..),
 ///     "rgba" => parse_rgba(..),
 ///     "hsl" => parse_hsl(..),
 ///     "hsla" => parse_hsla(..),
-///     name @ _ => Err(format!("unknown function: {}", name))
+///     _ => Err(format!("unknown function: {}", function_name))
 /// }
 /// # ;}
 /// # use std::ops::RangeFull;
 /// # fn parse_rgb(_: RangeFull) -> Result<(), String> { Ok(()) }
 /// # fn parse_rgba(_: RangeFull) -> Result<(), String> { Ok(()) }
 /// # fn parse_hsl(_: RangeFull) -> Result<(), String> { Ok(()) }
 /// # fn parse_hsla(_: RangeFull) -> Result<(), String> { Ok(()) }
 /// ```
@@ -77,17 +77,17 @@ macro_rules! match_ignore_ascii_case {
 ///     keyword(input).cloned()
 /// }
 #[macro_export]
 macro_rules! ascii_case_insensitive_phf_map {
     ($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr ),* }) => {
         ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )* })
     };
     ($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, )* }) => {
-        fn $name(input: &str) -> Option<&'static $ValueType> {
+        pub fn $name(input: &str) -> Option<&'static $ValueType> {
             cssparser_internal__invoke_proc_macro! {
                 cssparser_internal__phf_map!( ($ValueType) $( $key ($value) )+ )
             }
 
             {
                 cssparser_internal__invoke_proc_macro! {
                     cssparser_internal__max_len!( $( $key )+ )
                 }
--- a/third_party/rust/cssparser/src/unicode_range.rs
+++ b/third_party/rust/cssparser/src/unicode_range.rs
@@ -3,18 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! https://drafts.csswg.org/css-syntax/#urange
 
 use {Parser, ToCss};
 use std::char;
 use std::cmp;
 use std::fmt;
-use std::io::{self, Write};
-use tokenizer::{Token, NumericValue};
+use tokenizer::Token;
 
 /// One contiguous range of code points.
 ///
 /// Can not be empty. Can represent a single code point when start == end.
 #[derive(PartialEq, Eq, Clone, Hash)]
 pub struct UnicodeRange {
     /// Inclusive start of the range. In [0, end].
     pub start: u32,
@@ -30,127 +29,79 @@ impl UnicodeRange {
         //   u '+' <ident-token> '?'* |
         //   u <dimension-token> '?'* |
         //   u <number-token> '?'* |
         //   u <number-token> <dimension-token> |
         //   u <number-token> <number-token> |
         //   u '+' '?'+
 
         input.expect_ident_matching("u")?;
-
-        // Since start or end can’t be above 0x10FFFF, they can’t have more than 6 hex digits
-        // Conversely, input with more digits would end up returning Err anyway.
-        const MAX_LENGTH_AFTER_U_PLUS: usize = 6 + 1 + 6; // 6 digits, '-', 6 digits
-        let mut buffer = [0; MAX_LENGTH_AFTER_U_PLUS];
+        let after_u = input.position();
+        parse_tokens(input)?;
 
-        let remaining_len;
-        {
-            let mut remaining = &mut buffer[..];
-            concatenate_tokens(input, &mut remaining)?;
-            remaining_len = remaining.len();
-        }
+        // This deviates from the spec in case there are CSS comments
+        // between tokens in the middle of one <unicode-range>,
+        // but oh well…
+        let concatenated_tokens = input.slice_from(after_u);
 
-        let text_len = buffer.len() - remaining_len;
-        let text = &buffer[..text_len];
-        let range = parse_concatenated(text)?;
+        let range = parse_concatenated(concatenated_tokens.as_bytes())?;
         if range.end > char::MAX as u32 || range.start > range.end {
             Err(())
         } else {
             Ok(range)
         }
     }
 }
 
-fn concatenate_tokens(input: &mut Parser, remaining: &mut &mut [u8]) -> Result<(), Error> {
+fn parse_tokens(input: &mut Parser) -> Result<(), ()> {
     match input.next_including_whitespace()? {
         Token::Delim('+') => {
             match input.next_including_whitespace()? {
-                Token::Ident(ident) => remaining.write_all(ident.as_bytes())?,
-                Token::Delim('?') => remaining.write_all(b"?")?,
-                _ => return Err(Error)
+                Token::Ident(_) => {}
+                Token::Delim('?') => {}
+                _ => return Err(())
             }
-            parse_question_marks(input, remaining)
+            parse_question_marks(input)
         }
-
-        Token::Dimension(ref value, ref unit) => {
-            // Require a '+' sign as part of the number
-            let int_value = positive_integer_with_plus_sign(value)?;
-            write!(remaining, "{}{}", int_value, unit)?;
-            parse_question_marks(input, remaining)
+        Token::Dimension(..) => {
+            parse_question_marks(input)
         }
-
-        Token::Number(ref value) => {
-            // Require a '+' sign as part of the number
-            let int_value = positive_integer_with_plus_sign(value)?;
-            write!(remaining, "{}", int_value)?;
-
+        Token::Number(_) => {
             let after_number = input.position();
             match input.next_including_whitespace() {
-                Ok(Token::Delim('?')) => {
-                    // If `remaining` is already full, `int_value` has too many digits
-                    // so we can use `result?` Rust syntax.
-                    remaining.write_all(b"?")?;
-                    parse_question_marks(input, remaining)
-                }
-
-                Ok(Token::Dimension(ref value, ref unit)) => {
-                    // Require a '-' sign as part of the number
-                    let int_value = negative_integer(value)?;
-                    write!(remaining, "{}{}", int_value, unit)?
-                }
-
-                Ok(Token::Number(ref value)) => {
-                    // Require a '-' sign as part of the number
-                    let int_value = negative_integer(value)?;
-                    write!(remaining, "{}", int_value)?
-                }
-
+                Ok(Token::Delim('?')) => parse_question_marks(input),
+                Ok(Token::Dimension(..)) => {}
+                Ok(Token::Number(_)) => {}
                 _ => input.reset(after_number)
             }
         }
-
-        _ => return Err(Error)
+        _ => return Err(())
     }
     Ok(())
 }
 
-/// Consume as many '?' as possible and write them to `remaining` until it’s full
-fn parse_question_marks(input: &mut Parser, remaining: &mut &mut [u8]) {
+/// Consume as many '?' as possible
+fn parse_question_marks(input: &mut Parser) {
     loop {
-        let result = input.try(|input| {
-            match input.next_including_whitespace() {
-                Ok(Token::Delim('?')) => remaining.write_all(b"?").map_err(|_| ()),
-                _ => Err(())
+        let position = input.position();
+        match input.next_including_whitespace() {
+            Ok(Token::Delim('?')) => {}
+            _ => {
+                input.reset(position);
+                return
             }
-        });
-        if result.is_err() {
-            return
         }
     }
 }
 
-fn positive_integer_with_plus_sign(value: &NumericValue) -> Result<i32, ()> {
-    let int_value = value.int_value.ok_or(())?;
-    if value.has_sign && int_value >= 0 {
-        Ok(int_value)
-    } else {
-        Err(())
-    }
-}
-
-fn negative_integer(value: &NumericValue) -> Result<i32, ()> {  // Necessarily had a negative sign.
-    let int_value = value.int_value.ok_or(())?;
-    if int_value <= 0 {
-        Ok(int_value)
-    } else {
-        Err(())
-    }
-}
-
-fn parse_concatenated(mut text: &[u8]) -> Result<UnicodeRange, ()> {
+fn parse_concatenated(text: &[u8]) -> Result<UnicodeRange, ()> {
+    let mut text = match text.split_first() {
+        Some((&b'+', text)) => text,
+        _ => return Err(())
+    };
     let (first_hex_value, hex_digit_count) = consume_hex(&mut text);
     let question_marks = consume_question_marks(&mut text);
     let consumed = hex_digit_count + question_marks;
     if consumed == 0 || consumed > 6 {
         return Err(())
     }
 
     if question_marks > 0 {
@@ -236,23 +187,8 @@ impl ToCss for UnicodeRange {
             write!(dest, "{:X}", self.start)?;
             if self.end != self.start {
                 write!(dest, "-{:X}", self.end)?;
             }
         }
         Ok(())
     }
 }
-
-/// Make conversions from io::Error implicit in `?` syntax.
-struct Error;
-
-impl From<Error> for () {
-    fn from(_: Error) -> Self { () }
-}
-
-impl From<()> for Error {
-    fn from(_: ()) -> Self { Error }
-}
-
-impl From<io::Error> for Error {
-    fn from(_: io::Error) -> Self { Error }
-}
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -176,30 +176,30 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.12.2"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -297,17 +297,17 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
@@ -682,17 +682,17 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.18.0"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
@@ -762,17 +762,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring_vendor 0.1.0",
  "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -792,17 +792,17 @@ dependencies = [
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
 version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1088,18 +1088,18 @@ dependencies = [
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f98f0715ff67f27ca6a2f8f0ffc2a56f8edbc7acd57489c29eadc3a15c4eafe"
 "checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
 "checksum core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f51ce3b8ebe311c56de14231eb57572c15abebd2d32b3bcb99bcdb9c101f5ac3"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
 "checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
-"checksum cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb067f9d88368ca9053aea00581556151ef96f2591e32ad44f3312d7e6b67392"
-"checksum cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f0415de0bdbce823c0db204e00a62c8240fa2d3e04cd13ff7c6396e4446b95"
+"checksum cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b39404c5e04492194e3c69f1a10964b980f2c95c884a940f7903446779f6b027"
+"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
 "checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
 "checksum euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34559b159306de36203986eff799f83ef2bfb301a29fad333883f1a74a4cc6b0"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8728df930776135895cbb25cbdd17791cde7d4285d53cf58fe6ee2e6412455"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -174,30 +174,30 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.12.2"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -295,17 +295,17 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
@@ -669,17 +669,17 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.18.0"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
@@ -749,17 +749,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring_vendor 0.1.0",
  "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -779,17 +779,17 @@ dependencies = [
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
 version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1075,18 +1075,18 @@ dependencies = [
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f98f0715ff67f27ca6a2f8f0ffc2a56f8edbc7acd57489c29eadc3a15c4eafe"
 "checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
 "checksum core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f51ce3b8ebe311c56de14231eb57572c15abebd2d32b3bcb99bcdb9c101f5ac3"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
 "checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
-"checksum cssparser 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb067f9d88368ca9053aea00581556151ef96f2591e32ad44f3312d7e6b67392"
-"checksum cssparser-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f0415de0bdbce823c0db204e00a62c8240fa2d3e04cd13ff7c6396e4446b95"
+"checksum cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b39404c5e04492194e3c69f1a10964b980f2c95c884a940f7903446779f6b027"
+"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
 "checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
 "checksum euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34559b159306de36203986eff799f83ef2bfb301a29fad333883f1a74a4cc6b0"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8728df930776135895cbb25cbdd17791cde7d4285d53cf58fe6ee2e6412455"
--- a/widget/cocoa/OSXNotificationCenter.mm
+++ b/widget/cocoa/OSXNotificationCenter.mm
@@ -156,41 +156,41 @@ public:
   NS_DECL_ISUPPORTS
   OSXNotificationInfo(NSString *name, nsIObserver *observer,
                       const nsAString & alertCookie);
 
   NSString *mName;
   nsCOMPtr<nsIObserver> mObserver;
   nsString mCookie;
   RefPtr<nsICancelable> mIconRequest;
-  id<FakeNSUserNotification> mPendingNotifiction;
+  id<FakeNSUserNotification> mPendingNotification;
 };
 
 NS_IMPL_ISUPPORTS0(OSXNotificationInfo)
 
 OSXNotificationInfo::OSXNotificationInfo(NSString *name, nsIObserver *observer,
                                          const nsAString & alertCookie)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   NS_ASSERTION(name, "Cannot create OSXNotificationInfo without a name!");
   mName = [name retain];
   mObserver = observer;
   mCookie = alertCookie;
-  mPendingNotifiction = nil;
+  mPendingNotification = nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 OSXNotificationInfo::~OSXNotificationInfo()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [mName release];
-  [mPendingNotifiction release];
+  [mPendingNotification release];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static id<FakeNSUserNotificationCenter> GetNotificationCenter() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   Class c = NSClassFromString(@"NSUserNotificationCenter");
@@ -399,17 +399,17 @@ OSXNotificationCenter::ShowAlertWithIcon
     mActiveAlerts.AppendElement(osxni);
     [GetNotificationCenter() deliverNotification:notification];
     [notification release];
     if (aAlertListener) {
       aAlertListener->Observe(nullptr, "alertshow", cookie.get());
     }
   } else {
     mPendingAlerts.AppendElement(osxni);
-    osxni->mPendingNotifiction = notification;
+    osxni->mPendingNotification = notification;
     // Wait six seconds for the image to load.
     rv = aAlert->LoadImage(6000, this, osxni,
                            getter_AddRefs(osxni->mIconRequest));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       ShowPendingNotification(osxni);
     }
   }
 
@@ -525,35 +525,35 @@ OSXNotificationCenter::ShowPendingNotifi
   for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
     if (mPendingAlerts[i] == osxni) {
       mActiveAlerts.AppendElement(osxni);
       mPendingAlerts.RemoveElementAt(i);
       break;
     }
   }
 
-  [GetNotificationCenter() deliverNotification:osxni->mPendingNotifiction];
+  [GetNotificationCenter() deliverNotification:osxni->mPendingNotification];
 
   if (osxni->mObserver) {
     osxni->mObserver->Observe(nullptr, "alertshow", osxni->mCookie.get());
   }
 
-  [osxni->mPendingNotifiction release];
-  osxni->mPendingNotifiction = nil;
+  [osxni->mPendingNotification release];
+  osxni->mPendingNotification = nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 NS_IMETHODIMP
 OSXNotificationCenter::OnImageMissing(nsISupports* aUserData)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
-  if (osxni->mPendingNotifiction) {
+  if (osxni->mPendingNotification) {
     // If there was an error getting the image, or the request timed out, show
     // the notification without a content image.
     ShowPendingNotification(osxni);
   }
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
@@ -566,23 +566,23 @@ OSXNotificationCenter::OnImageReady(nsIS
 
   nsCOMPtr<imgIContainer> image;
   nsresult rv = aRequest->GetImage(getter_AddRefs(image));
   if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
     return rv;
   }
 
   OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
-  if (!osxni->mPendingNotifiction) {
+  if (!osxni->mPendingNotification) {
     return NS_ERROR_FAILURE;
   }
 
   NSImage *cocoaImage = nil;
   nsCocoaUtils::CreateNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, &cocoaImage, 1.0f);
-  (osxni->mPendingNotifiction).contentImage = cocoaImage;
+  (osxni->mPendingNotification).contentImage = cocoaImage;
   [cocoaImage release];
   ShowPendingNotification(osxni);
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
--- a/widget/reftests/reftest-stylo.list
+++ b/widget/reftests/reftest-stylo.list
@@ -1,7 +1,7 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 skip-if(!cocoaWidget) == 507947.html 507947.html
-fails == progressbar-fallback-default-style.html progressbar-fallback-default-style.html
+== progressbar-fallback-default-style.html progressbar-fallback-default-style.html
 == meter-native-style.html meter-native-style.html
 fails == meter-vertical-native-style.html meter-vertical-native-style.html
 fails == meter-fallback-default-style.html meter-fallback-default-style.html
 load 664925.xhtml
--- a/xpcom/base/ErrorList.py
+++ b/xpcom/base/ErrorList.py
@@ -1059,16 +1059,17 @@ with modules["DOM_ANIM"]:
 # =======================================================================
 with modules["DOM_PUSH"]:
     errors["NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR"] = FAILURE(1)
     errors["NS_ERROR_DOM_PUSH_DENIED_ERR"] = FAILURE(2)
     errors["NS_ERROR_DOM_PUSH_ABORT_ERR"] = FAILURE(3)
     errors["NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE"] = FAILURE(4)
     errors["NS_ERROR_DOM_PUSH_INVALID_KEY_ERR"] = FAILURE(5)
     errors["NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR"] = FAILURE(6)
+    errors["NS_ERROR_DOM_PUSH_GCM_DISABLED"] = FAILURE(7)
 
 
 # =======================================================================
 # 41: NS_ERROR_MODULE_DOM_MEDIA
 # =======================================================================
 with modules["DOM_MEDIA"]:
     # HTMLMediaElement API errors from https://html.spec.whatwg.org/multipage/embedded-content.html#media-elements
     errors["NS_ERROR_DOM_MEDIA_ABORT_ERR"] = FAILURE(1)