Merge inbound to mozilla-central. a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Wed, 29 Aug 2018 12:43:37 +0300
changeset 488873 b75561ff5ffe
parent 488872 56cfcee29fbc (current diff)
parent 488870 16018f6ec0c8 (diff)
child 488874 71c71ab3afae
child 488889 3876154fbae7
child 488930 51bf2c0d20e4
push id9734
push usershindli@mozilla.com
push dateThu, 30 Aug 2018 12:18:07 +0000
treeherdermozilla-beta@71c71ab3afae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
b75561ff5ffe / 63.0a1 / 20180829100131 / files
nightly linux64
b75561ff5ffe / 63.0a1 / 20180829100131 / files
nightly mac
b75561ff5ffe / 63.0a1 / 20180829100131 / files
nightly win32
b75561ff5ffe / 63.0a1 / 20180829100131 / files
nightly win64
b75561ff5ffe / 63.0a1 / 20180829100131 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/config/mozconfigs/linux64/debug-static-analysis-clang
browser/config/mozconfigs/linux64/opt-static-analysis-clang
gfx/ycbcr/QuellGccWarnings.patch
gfx/ycbcr/TypeFromSize.patch
gfx/ycbcr/clang-cl-workaround.patch
gfx/ycbcr/convert.patch
gfx/ycbcr/update.sh
gfx/ycbcr/win64.patch
layout/xul/crashtests/237787-1.xul
testing/mozharness/configs/builds/releng_sub_linux_configs/64_fuzzing_ccov.py
testing/mozharness/configs/builds/releng_sub_linux_configs/64_stat_and_debug.py
testing/mozharness/configs/builds/releng_sub_linux_configs/64_stat_and_opt.py
toolkit/content/xul.css
--- a/accessible/tests/mochitest/events/test_focus_listcontrols.xul
+++ b/accessible/tests/mochitest/events/test_focus_listcontrols.xul
@@ -45,33 +45,24 @@ if (!MAC) {
       let expectedItem = WIN ? "ml_strawberry" : "ml_marmalade";
       gQueue.push(new synthDownKey("menulist", new nofocusChecker(expectedItem)));
       gQueue.push(new synthOpenComboboxKey("menulist", new focusChecker(expectedItem)));
       gQueue.push(new synthEnterKey(expectedItem, new focusChecker("menulist")));
 } else {
       todo(false, "Bug 746531 - timeouts of last three menulist tests on OS X");
 }
 
-      var textentry = getAccessible("emenulist").firstChild;
-      gQueue.push(new synthFocus("emenulist", new focusChecker(textentry)));
-      gQueue.push(new synthDownKey(textentry, new nofocusChecker("eml_tangerine")));
-      gQueue.push(new synthUpKey(textentry, new focusChecker("eml_marmalade")));
-      gQueue.push(new synthEnterKey("eml_marmalade", new focusChecker(textentry)));
-      gQueue.push(new synthOpenComboboxKey("emenulist", new focusChecker("eml_marmalade")));
-      gQueue.push(new synthEscapeKey("eml_marmalade", new focusChecker(textentry)));
-
       // no focus events for unfocused list controls when current item is
       // changed.
       gQueue.push(new synthFocus("emptyrichlistbox"));
 
       gQueue.push(new changeCurrentItem("richlistbox", "rlb_item1"));
 if (!MAC) {
       gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine"));
 }
-      gQueue.push(new changeCurrentItem("emenulist", "eml_tangerine"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 
@@ -119,19 +110,13 @@ if (!MAC) {
 
       <menulist id="menulist">
         <menupopup>
           <menuitem id="ml_tangerine" label="tangerine trees"/>
           <menuitem id="ml_marmalade" label="marmalade skies"/>
           <menuitem id="ml_strawberry" label="strawberry fields"/>
         </menupopup>
       </menulist>
-      <menulist id="emenulist" editable="true">
-        <menupopup>
-          <menuitem id="eml_tangerine" label="tangerine trees"/>
-          <menuitem id="eml_marmalade" label="marmalade skies"/>
-        </menupopup>
-      </menulist>
 
       <vbox id="eventdump"/>
     </vbox>
   </hbox>
 </window>
--- a/accessible/tests/mochitest/tree/test_combobox.xul
+++ b/accessible/tests/mochitest/tree/test_combobox.xul
@@ -50,58 +50,16 @@
             ]
           }
         ]
       };
 
       testAccessibleTree("menulist", accTree);
 
       //////////////////////////////////////////////////////////////////////////
-      // editable menulist
-
-      accTree = {
-        role: ROLE_COMBOBOX,
-        children: [
-          {
-            role: ROLE_ENTRY,
-            children: [
-              // no text leaf accessible for text node
-            ]
-          },
-          {
-            role: ROLE_COMBOBOX_LIST, // context menu
-            children: []
-          },
-          {
-            role: ROLE_PUSHBUTTON, // dropmarker
-            children: []
-          },
-          {
-            role: ROLE_COMBOBOX_LIST, // option list
-            children: [
-              {
-                role: ROLE_COMBOBOX_OPTION,
-                children: []
-              },
-              {
-                role: ROLE_COMBOBOX_OPTION,
-                children: []
-              }
-            ]
-          }
-        ]
-      };
-
-      if (!MAC) {
-        testAccessibleTree("menulist2", accTree);
-      } else {
-        todo(false, "Make this test pass on OSX (bug 551957)");
-      }
-
-      //////////////////////////////////////////////////////////////////////////
       // textbox@type=autocomplete #1 (history)
 
       accTree = {
         // textbox
         role: ROLE_AUTOCOMPLETE,
         children: [
           {
             // html:input
@@ -190,23 +148,16 @@
     <vbox flex="1">
       <menulist id="menulist">
         <menupopup>
           <menuitem label="item"/>
           <menuitem label="item"/>
         </menupopup>
       </menulist>
 
-      <menulist id="menulist2" editable="true">
-        <menupopup>
-          <menuitem label="item"/>
-          <menuitem label="item"/>
-        </menupopup>
-      </menulist>
-
       <textbox id="autocomplete" type="autocomplete"
                autocompletesearch="unifiedcomplete"
                value="http://mochi.test:8888/redirect-a11y.html"/>
 
       <textbox id="autocomplete2" type="autocomplete">
         <menupopup>
           <menuitem label="item1"/>
         </menupopup>
--- a/accessible/xul/XULComboboxAccessible.cpp
+++ b/accessible/xul/XULComboboxAccessible.cpp
@@ -27,23 +27,20 @@ XULComboboxAccessible::
   AccessibleWrap(aContent, aDoc)
 {
   if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                          nsGkAtoms::autocomplete, eIgnoreCase))
     mGenericTypes |= eAutoComplete;
   else
     mGenericTypes |= eCombobox;
 
-  // Both the XUL <textbox type="autocomplete"> and <menulist editable="true">
-  // widgets use XULComboboxAccessible. We need to walk the anonymous children
-  // for these so that the entry field is a child. Otherwise no XBL children.
-  if (!mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL) &&
-      !mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                          nsGkAtoms::editable, nsGkAtoms::_true,
-                                          eIgnoreCase)) {
+  // The XUL <textbox type="autocomplete"> uses XULComboboxAccessible. We need
+  // to walk the anonymous children for these so that the entry field is a
+  // child. Otherwise no XBL children.
+  if (!mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL)) {
     mStateFlags |= eNoXBLKids;
   }
 }
 
 role
 XULComboboxAccessible::NativeRole() const
 {
   return IsAutoComplete() ? roles::AUTOCOMPLETE : roles::COMBOBOX;
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -980,11 +980,12 @@ let ChromeURLBlockPolicy = {
 
 function blockAllChromeURLs() {
   let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
   registrar.registerFactory(ChromeURLBlockPolicy.classID,
                             ChromeURLBlockPolicy.classDescription,
                             ChromeURLBlockPolicy.contractID,
                             ChromeURLBlockPolicy);
 
-  let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
-  cm.addCategoryEntry("content-policy", ChromeURLBlockPolicy.contractID, ChromeURLBlockPolicy.contractID, false, true);
+  Services.catMan.addCategoryEntry("content-policy",
+                                   ChromeURLBlockPolicy.contractID,
+                                   ChromeURLBlockPolicy.contractID, false, true);
 }
--- a/browser/components/payments/content/paymentDialogFrameScript.js
+++ b/browser/components/payments/content/paymentDialogFrameScript.js
@@ -75,16 +75,21 @@ let PaymentFrameScript = {
     let PaymentDialogUtils = {
       DEFAULT_REGION: FormAutofill.DEFAULT_REGION,
       supportedCountries: FormAutofill.supportedCountries,
 
       getAddressLabel(address, addressFields = null) {
         return FormAutofillUtils.getAddressLabel(address, addressFields);
       },
 
+      getCreditCardNetworks() {
+        let networks = FormAutofillUtils.getCreditCardNetworks();
+        return Cu.cloneInto(networks, waivedContent);
+      },
+
       isCCNumber(value) {
         return FormAutofillUtils.isCCNumber(value);
       },
 
       getFormFormat(country) {
         let format = FormAutofillUtils.getFormFormat(country);
         return Cu.cloneInto(format, waivedContent);
       },
--- a/browser/components/payments/res/containers/address-form.css
+++ b/browser/components/payments/res/containers/address-form.css
@@ -1,17 +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/. */
 
-/* Hide the message about autofill availability since it's not relevant */
-#country-warning-message {
-  display: none;
-}
-
 .error-text:not(:empty) {
   color: #fff;
   background-color: #d70022;
   border-radius: 2px;
   /* The padding-top and padding-bottom are referenced by address-form.js */
   padding: 5px 12px;
   position: absolute;
   z-index: 1;
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -268,17 +268,17 @@ export default class AddressForm extends
   }
 
   updateRequiredState() {
     for (let field of this.form.elements) {
       let container = field.closest(`#${field.id}-container`);
       if (field.localName == "button" || !container) {
         continue;
       }
-      let span = container.querySelector("span");
+      let span = container.querySelector(".label-text");
       span.setAttribute("fieldRequiredSymbol", this.dataset.fieldRequiredSymbol);
       let required = field.required && !field.disabled;
       if (required) {
         container.setAttribute("required", "true");
       } else {
         container.removeAttribute("required");
       }
     }
--- a/browser/components/payments/res/containers/basic-card-form.js
+++ b/browser/components/payments/res/containers/basic-card-form.js
@@ -79,16 +79,17 @@ export default class BasicCardForm exten
 
       let record = {};
       let addresses = [];
       this.formHandler = new EditCreditCard({
         form,
       }, record, addresses, {
         isCCNumber: PaymentDialogUtils.isCCNumber,
         getAddressLabel: PaymentDialogUtils.getAddressLabel,
+        getSupportedNetworks: PaymentDialogUtils.getCreditCardNetworks,
       });
 
       // The EditCreditCard constructor adds `input` event listeners on the same element,
       // which update field validity. By adding our event listeners after this constructor,
       // validity will be updated before our handlers get the event
       form.addEventListener("input", this);
       form.addEventListener("invalid", this);
 
@@ -307,21 +308,21 @@ export default class BasicCardForm exten
     this.saveButton.disabled = true;
   }
 
   updateSaveButtonState() {
     this.saveButton.disabled = !this.form.checkValidity();
   }
 
   updateRequiredState() {
-    for (let formElement of this.form.elements) {
-      let container = formElement.closest("label") || formElement.closest("div");
-      let span = container.querySelector("span");
+    for (let field of this.form.elements) {
+      let container = field.closest(".container");
+      let span = container.querySelector(".label-text");
       span.setAttribute("fieldRequiredSymbol", this.dataset.fieldRequiredSymbol);
-      let required = formElement.required && !formElement.disabled;
+      let required = field.required && !field.disabled;
       if (required) {
         container.setAttribute("required", "true");
       } else {
         container.removeAttribute("required");
       }
     }
   }
 
--- a/browser/components/payments/res/unprivileged-fallbacks.js
+++ b/browser/components/payments/res/unprivileged-fallbacks.js
@@ -25,22 +25,62 @@ var PaymentDialogUtils = {
   getAddressLabel(address, addressFields = null) {
     if (addressFields) {
       let requestedFields = addressFields.trim().split(/\s+/);
       return requestedFields.filter(f => f && address[f]).map(f => address[f]).join(", ") +
         ` (${address.guid})`;
     }
     return `${address.name} (${address.guid})`;
   },
+
+  getCreditCardNetworks(address) {
+    // Shim for list of known and supported credit card network ids as exposed by
+    // toolkit/modules/CreditCard.jsm
+    return [
+      "amex",
+      "cartebancaire",
+      "diners",
+      "discover",
+      "jcb",
+      "mastercard",
+      "mir",
+      "unionpay",
+      "visa",
+    ];
+  },
   isCCNumber(str) {
     return !!str.replace(/[-\s]/g, "").match(/^\d{9,}$/);
   },
   DEFAULT_REGION: "US",
-  supportedCountries: ["US", "CA"],
+  supportedCountries: ["US", "CA", "DE"],
   getFormFormat(country) {
+    if (country == "DE") {
+      return {
+        addressLevel1Label: "province",
+        postalCodeLabel: "postalCode",
+        fieldsOrder: [
+          {
+            fieldId: "name",
+            newLine: true,
+          },
+          {
+            fieldId: "organization",
+            newLine: true,
+          },
+          {
+            fieldId: "street-address",
+            newLine: true,
+          },
+          {fieldId: "postal-code"},
+          {fieldId: "address-level2"},
+        ],
+        postalCodePattern: "\\d{5}",
+      };
+    }
+
     return {
       "addressLevel1Label": country == "US" ? "state" : "province",
       "postalCodeLabel": country == "US" ? "zip" : "postalCode",
       "fieldsOrder": [
         {fieldId: "name", newLine: true},
         {fieldId: "organization", newLine: true},
         {fieldId: "street-address", newLine: true},
         {fieldId: "address-level2"},
--- a/browser/components/payments/test/PaymentTestUtils.jsm
+++ b/browser/components/payments/test/PaymentTestUtils.jsm
@@ -477,27 +477,30 @@ var PaymentTestUtils = {
   },
 
   BasicCards: {
     JohnDoe: {
       "cc-exp-month": 1,
       "cc-exp-year": (new Date()).getFullYear() + 9,
       "cc-name": "John Doe",
       "cc-number": "4111111111111111",
+      "cc-type": "visa",
     },
     JaneMasterCard: {
       "cc-exp-month": 12,
       "cc-exp-year": (new Date()).getFullYear() + 9,
       "cc-name": "Jane McMaster-Card",
       "cc-number": "5555555555554444",
+      "cc-type": "mastercard",
     },
     MissingFields: {
       "cc-name": "Missy Fields",
       "cc-number": "340000000000009",
     },
     Temp: {
       "cc-exp-month": 12,
       "cc-exp-year": (new Date()).getFullYear() + 9,
       "cc-name": "Temp Name",
       "cc-number": "5105105105105100",
+      "cc-type": "mastercard",
     },
   },
 };
--- a/browser/components/payments/test/browser/browser_card_edit.js
+++ b/browser/components/payments/test/browser/browser_card_edit.js
@@ -45,22 +45,25 @@ async function add_link(aOptions = {}) {
 
       is(state.isPrivate, testArgs.isPrivate,
          "isPrivate flag has expected value when shown from a private/non-private session");
     }, aOptions);
 
     let cardOptions = Object.assign({}, {
       checkboxSelector: "basic-card-form .persist-checkbox",
       expectPersist: aOptions.expectCardPersist,
+      networkSelector: "basic-card-form #cc-type",
+      expectedNetwork: PTU.BasicCards.JaneMasterCard["cc-type"],
     });
     if (aOptions.hasOwnProperty("setCardPersistCheckedValue")) {
       cardOptions.setPersistCheckedValue = aOptions.setCardPersistCheckedValue;
     }
     await fillInCardForm(frame, PTU.BasicCards.JaneMasterCard, cardOptions);
 
+    await verifyCardNetwork(frame, cardOptions);
     await verifyPersistCheckbox(frame, cardOptions);
 
     await spawnPaymentDialogTask(frame, async function checkBillingAddressPicker(testArgs = {}) {
       let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
       ok(content.isVisible(billingAddressSelect),
          "The billing address selector should always be visible");
       is(billingAddressSelect.childElementCount, 2,
          "Only 2 child options should exist by default");
@@ -514,16 +517,77 @@ add_task(async function test_edit_link()
     }
 
     state = await PTU.DialogContentUtils.waitForState(content, (state) => {
       return state.page.id == "payment-summary";
     }, "Switched back to payment-summary");
   }, args);
 });
 
+add_task(async function test_invalid_network_card_edit() {
+  // add an address and card linked to this address
+  let prefilledGuids = await setup([PTU.Addresses.TimBL]);
+  {
+    let card = Object.assign({}, PTU.BasicCards.JohnDoe,
+                             { billingAddressGUID: prefilledGuids.address1GUID });
+    // create a record with an unknown network id
+    card["cc-type"] = "asiv";
+    await addCardRecord(card);
+  }
+
+  const args = {
+    methodData: [PTU.MethodData.basicCard],
+    details: PTU.Details.total60USD,
+  };
+  await spawnInDialogForMerchantTask(PTU.ContentTasks.createAndShowRequest, async function check() {
+    let {
+      PaymentTestUtils: PTU,
+    } = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
+
+    let editLink = content.document.querySelector("payment-method-picker .edit-link");
+    is(editLink.textContent, "Edit", "Edit link text");
+
+    editLink.click();
+
+    let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
+      return state.page.id == "basic-card-page" && state["basic-card-page"].guid;
+    }, "Check edit page state");
+
+    state = await PTU.DialogContentUtils.waitForState(content, (state) => {
+      return Object.keys(state.savedBasicCards).length == 1 &&
+             Object.keys(state.savedAddresses).length == 1;
+    }, "Check card and address present at beginning of test");
+
+    let networkSelector = content.document.querySelector("basic-card-form #cc-type");
+    todo_is(Cu.waiveXrays(networkSelector).selectedIndex, 0,
+            "An invalid cc-type should result in the first option being selected");
+    is(Cu.waiveXrays(networkSelector).value, "",
+       "An invalid cc-type should result in an empty string as value");
+
+    content.document.querySelector("basic-card-form button.save-button").click();
+
+    // we expect that saving a card with an invalid network will result in the
+    // cc-type property being changed to undefined
+    state = await PTU.DialogContentUtils.waitForState(content, (state) => {
+      let cards = Object.entries(state.savedBasicCards);
+      return cards.length == 1 &&
+             cards[0][1]["cc-type"] == undefined;
+    }, "Check card was edited");
+
+    let cardGUIDs = Object.keys(state.savedBasicCards);
+    is(cardGUIDs.length, 1, "Check there is still one card");
+    let savedCard = state.savedBasicCards[cardGUIDs[0]];
+    ok(!savedCard["cc-type"], "We expect the cc-type value to be updated");
+
+    state = await PTU.DialogContentUtils.waitForState(content, (state) => {
+      return state.page.id == "payment-summary";
+    }, "Switched back to payment-summary");
+  }, args);
+});
+
 add_task(async function test_private_card_adding() {
   await setup([PTU.Addresses.TimBL], [PTU.BasicCards.JohnDoe]);
   let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
 
   await BrowserTestUtils.withNewTab({
     gBrowser: privateWin.gBrowser,
     url: BLANK_PAGE_URL,
   }, async browser => {
@@ -586,8 +650,9 @@ add_task(async function test_private_car
       ok(tempCard["cc-exp"], "cc-exp was computed");
       ok(tempCard["cc-number-encrypted"], "cc-number-encrypted was computed");
     });
     spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
     await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
   });
   await BrowserTestUtils.closeWindow(privateWin);
 });
+
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -17,16 +17,17 @@ const SAVE_ADDRESS_DEFAULT_PREF = "dom.p
 const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"]
                      .getService(Ci.nsIPaymentRequestService);
 const paymentUISrv = Cc["@mozilla.org/dom/payments/payment-ui-service;1"]
                      .getService().wrappedJSObject;
 const {formAutofillStorage} = ChromeUtils.import(
   "resource://formautofill/FormAutofillStorage.jsm", {});
 const {PaymentTestUtils: PTU} = ChromeUtils.import(
   "resource://testing-common/PaymentTestUtils.jsm", {});
+ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
 
 function getPaymentRequests() {
   return Array.from(paymentSrv.enumerate());
 }
 
 /**
  * Return the container (e.g. dialog or overlay) that the payment request contents are shown in.
  * This abstracts away the details of the widget used so that this can more earily transition from a
@@ -352,16 +353,19 @@ add_task(async function setup_head() {
   await setupFormAutofillStorage();
   registerCleanupFunction(function cleanup() {
     paymentSrv.cleanup();
     cleanupFormAutofillStorage();
     Services.prefs.clearUserPref(RESPONSE_TIMEOUT_PREF);
     Services.prefs.clearUserPref(SAVE_CREDITCARD_DEFAULT_PREF);
     Services.prefs.clearUserPref(SAVE_ADDRESS_DEFAULT_PREF);
     SpecialPowers.postConsoleSentinel();
+    // CreditCard.jsm is imported into the global scope. It needs to be deleted
+    // else it outlives the test and is reported as a leak.
+    delete window.CreditCard;
   });
 });
 
 function deepClone(obj) {
   return JSON.parse(JSON.stringify(obj));
 }
 
 async function selectPaymentDialogShippingAddressByCountry(frame, country) {
@@ -470,16 +474,35 @@ async function verifyPersistCheckbox(fra
     } else {
       ok(!persistCheckbox.hidden, "checkbox should be visible when adding a new record");
       is(persistCheckbox.checked, options.expectPersist,
          `persist checkbox state is expected to be ${options.expectPersist}`);
     }
   }, {options: aOptions});
 }
 
+async function verifyCardNetwork(frame, aOptions = {}) {
+  aOptions.supportedNetworks = CreditCard.SUPPORTED_NETWORKS;
+
+  await spawnPaymentDialogTask(frame, async (args) => {
+    let {options = {}} = args;
+    // ensure the network picker is visible, has the right contents and expected value
+    let networkSelect = Cu.waiveXrays(
+        content.document.querySelector(options.networkSelector));
+    ok(content.isVisible(networkSelect),
+       "The network selector should always be visible");
+    is(networkSelect.childElementCount, options.supportedNetworks.length + 1,
+       "Should have one more than the number of supported networks");
+    is(networkSelect.children[0].value, "",
+       "The first option should be the blank/empty option");
+    is(networkSelect.value, options.expectedNetwork,
+       `The network picker should have the expected value`);
+  }, {options: aOptions});
+}
+
 async function submitAddressForm(frame, aAddress, aOptions = {}) {
   await spawnPaymentDialogTask(frame, async (args) => {
     let {options = {}} = args;
     let {
       PaymentTestUtils,
     } = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
 
     let oldAddresses = await PaymentTestUtils.DialogContentUtils.getCurrentState(content);
--- a/browser/components/payments/test/mochitest/test_basic_card_form.html
+++ b/browser/components/payments/test/mochitest/test_basic_card_form.html
@@ -37,16 +37,17 @@ let display = document.getElementById("d
 
 function checkCCForm(customEl, expectedCard) {
   const CC_PROPERTY_NAMES = [
     "billingAddressGUID",
     "cc-number",
     "cc-name",
     "cc-exp-month",
     "cc-exp-year",
+    "cc-type",
   ];
   for (let propName of CC_PROPERTY_NAMES) {
     let expectedVal = expectedCard[propName] || "";
     is(document.getElementById(propName).value,
        expectedVal.toString(),
        `Check ${propName}`);
   }
 }
@@ -105,16 +106,17 @@ add_task(async function test_saveButton(
   fillField(form.form.querySelector("#cc-number"), "4111 1111-1111 1111");
   form.form.querySelector("#cc-name").focus();
   // Check .disabled after .focus() so that it's after both "input" and "change" events.
   ok(form.saveButton.disabled, "Save button should still be disabled without a name");
   sendString("J. Smith");
   fillField(form.form.querySelector("#cc-exp-month"), "11");
   let year = (new Date()).getFullYear().toString();
   fillField(form.form.querySelector("#cc-exp-year"), year);
+  fillField(form.form.querySelector("#cc-type"), "visa");
   form.saveButton.focus();
   ok(!form.saveButton.disabled,
      "Save button should be enabled since the required fields are filled");
 
   info("blanking the cc-number field");
   fillField(form.form.querySelector("#cc-number"), "");
   ok(form.saveButton.disabled, "Save button is disabled after blanking cc-number");
   form.form.querySelector("#cc-number").blur();
@@ -138,16 +140,17 @@ add_task(async function test_saveButton(
     collectionName: "creditCards",
     guid: undefined,
     messageType: "updateAutofillRecord",
     record: {
       "cc-exp-month": "11",
       "cc-exp-year": year,
       "cc-name": "J. Smith",
       "cc-number": "4111 1111-1111 1111",
+      "cc-type": "visa",
       "billingAddressGUID": "",
       "isTemporary": true,
     },
   }, "Check event details for the message to chrome");
   form.remove();
 });
 
 add_task(async function test_requiredAttributePropagated() {
@@ -434,12 +437,43 @@ add_task(async function test_numberCusto
     "basic-card-page": {
     },
   });
 
   ok(!form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is not visibly invalid");
 
   form.remove();
 });
+
+add_task(async function test_noCardNetworkSelected() {
+  let form = new BasicCardForm();
+  await form.promiseReady;
+  display.appendChild(form);
+  await asyncElementRendered();
+
+  info("have an existing card in storage, with no network id");
+  let card1 = deepClone(PTU.BasicCards.JohnDoe);
+  card1.guid = "9864798564";
+  delete card1["cc-type"];
+
+  await form.requestStore.setState({
+    page: {
+      id: "basic-card-page",
+    },
+    "basic-card-page": {
+      guid: card1.guid,
+    },
+    savedBasicCards: {
+      [card1.guid]: deepClone(card1),
+    },
+  });
+  await asyncElementRendered();
+  checkCCForm(form, card1);
+  is(document.getElementById("cc-type").selectedIndex, 0, "Initial empty option is selected");
+
+  form.remove();
+  await form.requestStore.reset();
+});
+
 </script>
 
 </body>
 </html>
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -15,17 +15,16 @@ ChromeUtils.import("resource:///modules/
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm");
 ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm");
 ChromeUtils.import("resource://gre/modules/Localization.jsm");
 ChromeUtils.defineModuleGetter(this, "CloudStorage",
   "resource://gre/modules/CloudStorage.jsm");
 
 XPCOMUtils.defineLazyServiceGetters(this, {
-  gCategoryManager: ["@mozilla.org/categorymanager;1", "nsICategoryManager"],
   gHandlerService: ["@mozilla.org/uriloader/handler-service;1", "nsIHandlerService"],
   gMIMEService: ["@mozilla.org/mime;1", "nsIMIMEService"],
 });
 
 // Constants & Enumeration Values
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
 const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
@@ -2845,32 +2844,32 @@ class HandlerInfoWrapper {
 
     if (!disabledPluginTypes.includes(this.type))
       disabledPluginTypes.push(this.type);
 
     Services.prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
       disabledPluginTypes.join(","));
 
     // Update the category manager so existing browser windows update.
-    gCategoryManager.deleteCategoryEntry("Gecko-Content-Viewers",
+    Services.catMan.deleteCategoryEntry("Gecko-Content-Viewers",
       this.type,
       false);
   }
 
   enablePluginType() {
     var disabledPluginTypes = this._getDisabledPluginTypes();
 
     var type = this.type;
     disabledPluginTypes = disabledPluginTypes.filter(v => v != type);
 
     Services.prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
       disabledPluginTypes.join(","));
 
     // Update the category manager so existing browser windows update.
-    gCategoryManager.addCategoryEntry(
+    Services.catMan.addCategoryEntry(
       "Gecko-Content-Viewers",
       this.type,
       "@mozilla.org/content/plugin/document-loader-factory;1",
       false,
       true);
   }
 
   store() {
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/linux64/fuzzing-ccov
@@ -0,0 +1,15 @@
+MOZ_AUTOMATION_L10N_CHECK=0
+
+. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
+
+ac_add_options --disable-install-strip
+ac_add_options --disable-elf-hack
+ac_add_options --disable-sandbox
+ac_add_options --disable-profiling
+ac_add_options --disable-warnings-as-errors
+ac_add_options --enable-coverage
+
+export CFLAGS="--coverage"
+export CXXFLAGS="--coverage"
+export LDFLAGS="--coverage"
+ac_add_options --enable-fuzzing
deleted file mode 100644
--- a/browser/config/mozconfigs/linux64/opt-static-analysis-clang
+++ /dev/null
@@ -1,20 +0,0 @@
-MOZ_AUTOMATION_BUILD_SYMBOLS=0
-MOZ_AUTOMATION_PACKAGE_TESTS=0
-MOZ_AUTOMATION_L10N_CHECK=0
-
-. "$topsrcdir/build/mozconfig.common"
-
-ac_add_options --enable-dmd
-
-. $topsrcdir/build/mozconfig.stylo
-
-# Use Clang as specified in manifest
-CC="$topsrcdir/clang/bin/clang"
-CXX="$topsrcdir/clang/bin/clang++"
-
-# Add the static checker
-ac_add_options --enable-clang-plugin
-
-. "$topsrcdir/build/unix/mozconfig.stdcxx"
-
-. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/tup
+++ b/browser/config/mozconfigs/linux64/tup
@@ -9,11 +9,12 @@ MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 export TUP=${TOOLTOOL_DIR}/tup/tup
 
 . "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
 . "$topsrcdir/build/mozconfig.common.override"
 
 ac_add_options --enable-build-backends=Tup
 ac_add_options --disable-js-shell
+unset ENABLE_CLANG_PLUGIN
 # To enable the option to upload the tup database, uncomment the line below
 # ac_add_options --upload-tup-db
 
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -459,16 +459,21 @@ FormAutofillParent.prototype = {
     // Updates the used status for shield/heartbeat to recognize users who have
     // used Credit Card Autofill.
     let setUsedStatus = status => {
       if (FormAutofill.AutofillCreditCardsUsedStatus < status) {
         Services.prefs.setIntPref(FormAutofill.CREDITCARDS_USED_STATUS_PREF, status);
       }
     };
 
+    // Remove invalid cc-type values
+    if (creditCard.record["cc-type"] && !CreditCard.isValidNetwork(creditCard.record["cc-type"])) {
+      delete creditCard.record["cc-type"];
+    }
+
     // We'll show the credit card doorhanger if:
     //   - User applys autofill and changed
     //   - User fills form manually and the filling data is not duplicated to storage
     if (creditCard.guid) {
       // Indicate that the user has used Credit Card Autofill to fill in a form.
       setUsedStatus(3);
 
       let originalCCData = this.formAutofillStorage.creditCards.get(creditCard.guid);
@@ -523,16 +528,17 @@ FormAutofillParent.prototype = {
       if (!FormAutofill.isAutofillCreditCardsEnabled) {
         return;
       }
 
       const card = new CreditCard({
         number: creditCard.record["cc-number"] || creditCard.record["cc-number-decrypted"],
         encryptedNumber: creditCard.record["cc-number-encrypted"],
         name: creditCard.record["cc-name"],
+        network: creditCard.record["cc-type"],
       });
       const description = await card.getLabel();
       const state = await FormAutofillDoorhanger.show(target,
                                                       creditCard.guid ? "updateCreditCard" : "addCreditCard",
                                                       description);
       if (state == "cancel") {
         return;
       }
--- a/browser/extensions/formautofill/FormAutofillStorage.jsm
+++ b/browser/extensions/formautofill/FormAutofillStorage.jsm
@@ -61,16 +61,17 @@
  *                                which may or may not exist locally.
  *
  *       cc-name,
  *       cc-number,            // will be stored in masked format (************1234)
  *                             // (see details below)
  *       cc-exp-month,
  *       cc-exp-year,          // 2-digit year will be converted to 4 digits
  *                             // upon saving
+ *       cc-type,              // Optional card network id (instrument type)
  *
  *       // computed fields (These fields are computed based on the above fields
  *       // and are not allowed to be modified directly.)
  *       cc-given-name,
  *       cc-additional-name,
  *       cc-family-name,
  *       cc-number-encrypted,  // encrypted from the original unmasked "cc-number"
  *                             // (see details below)
@@ -193,16 +194,17 @@ const VALID_ADDRESS_COMPUTED_FIELDS = [
 ].concat(STREET_ADDRESS_COMPONENTS, TEL_COMPONENTS);
 
 const VALID_CREDIT_CARD_FIELDS = [
   "billingAddressGUID",
   "cc-name",
   "cc-number",
   "cc-exp-month",
   "cc-exp-year",
+  "cc-type",
 ];
 
 const VALID_CREDIT_CARD_COMPUTED_FIELDS = [
   "cc-given-name",
   "cc-additional-name",
   "cc-family-name",
   "cc-number-encrypted",
   "cc-exp",
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -13,17 +13,17 @@ const ADDRESS_REFERENCES_EXT = "addressR
 const ADDRESSES_COLLECTION_NAME = "addresses";
 const CREDITCARDS_COLLECTION_NAME = "creditCards";
 const MANAGE_ADDRESSES_KEYWORDS = ["manageAddressesTitle", "addNewAddressTitle"];
 const EDIT_ADDRESS_KEYWORDS = [
   "givenName", "additionalName", "familyName", "organization2", "streetAddress",
   "state", "province", "city", "country", "zip", "postalCode", "email", "tel",
 ];
 const MANAGE_CREDITCARDS_KEYWORDS = ["manageCreditCardsTitle", "addNewCreditCardTitle", "showCreditCardsBtnLabel"];
-const EDIT_CREDITCARD_KEYWORDS = ["cardNumber", "nameOnCard", "cardExpiresMonth", "cardExpiresYear"];
+const EDIT_CREDITCARD_KEYWORDS = ["cardNumber", "nameOnCard", "cardExpiresMonth", "cardExpiresYear", "cardNetwork"];
 const FIELD_STATES = {
   NORMAL: "NORMAL",
   AUTO_FILLED: "AUTO_FILLED",
   PREVIEW: "PREVIEW",
 };
 const SECTION_TYPES = {
   ADDRESS: "address",
   CREDIT_CARD: "creditCard",
@@ -201,16 +201,17 @@ this.FormAutofillUtils = {
     "cc-name": "creditCard",
     "cc-given-name": "creditCard",
     "cc-additional-name": "creditCard",
     "cc-family-name": "creditCard",
     "cc-number": "creditCard",
     "cc-exp-month": "creditCard",
     "cc-exp-year": "creditCard",
     "cc-exp": "creditCard",
+    "cc-type": "creditCard",
   },
 
   _collators: {},
   _reAlternativeCountryNames: {},
 
   isAddressField(fieldName) {
     return !!this._fieldNameInfo[fieldName] && !this.isCreditCardField(fieldName);
   },
@@ -219,16 +220,25 @@ this.FormAutofillUtils = {
     return this._fieldNameInfo[fieldName] == "creditCard";
   },
 
   isCCNumber(ccNumber) {
     let card = new CreditCard({number: ccNumber});
     return card.isValidNumber();
   },
 
+  /**
+   * Get the array of credit card network ids ("types") we expect and offer as valid choices
+   *
+   * @returns {Array}
+   */
+  getCreditCardNetworks() {
+    return CreditCard.SUPPORTED_NETWORKS;
+  },
+
   getCategoryFromFieldName(fieldName) {
     return this._fieldNameInfo[fieldName];
   },
 
   getCategoriesFromFieldNames(fieldNames) {
     let categories = new Set();
     for (let fieldName of fieldNames) {
       let info = this.getCategoryFromFieldName(fieldName);
@@ -697,16 +707,27 @@ this.FormAutofillUtils = {
           if ([option.text, option.label, option.value].some(
             str => patterns.some(pattern => str.includes(pattern))
           )) {
             return option;
           }
         }
         break;
       }
+      case "cc-type": {
+        let network = creditCard["cc-type"] || "";
+        for (let option of options) {
+          if ([option.text, option.label, option.value].some(
+            s => s.trim().toLowerCase() == network
+          )) {
+            return option;
+          }
+        }
+        break;
+      }
     }
 
     return null;
   },
 
   /**
    * Try to match value with keys and names, but always return the key.
    * @param   {array<string>} keys
--- a/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js
+++ b/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js
@@ -8,10 +8,13 @@
 "use strict";
 
 // "addressDataExt" uses the same key as "addressData" in "addressReferences.js" and contains
 //  contains the information we need but absent in "libaddressinput" such as alternative names.
 
 // TODO: We only support the alternative name of US in MVP. We are going to support more countries in
 //       bug 1370193.
 var addressDataExt = {
-  "data/US": {"alternative_names": ["US", "United States of America", "United States", "America", "U.S.", "USA", "U.S.A.", "U.S.A"]},
+  "data/US": {
+    alternative_names: ["US", "United States of America", "United States", "America", "U.S.", "USA", "U.S.A.", "U.S.A"],
+    fmt: "%N%n%A%n%C%S%n%Z%O",
+  },
 };
--- a/browser/extensions/formautofill/content/autofillEditForms.js
+++ b/browser/extensions/formautofill/content/autofillEditForms.js
@@ -296,41 +296,45 @@ class EditAddress extends EditAutofillFo
 
 class EditCreditCard extends EditAutofillForm {
   /**
    * @param {HTMLElement[]} elements
    * @param {object} record with a decrypted cc-number
    * @param {object} addresses in an object with guid keys for the billing address picker.
    * @param {object} config
    * @param {function} config.isCCNumber Function to determine if a string is a valid CC number.
+   * @param {function} config.getSupportedNetworks Function to get the list of card networks
    */
   constructor(elements, record, addresses, config) {
     super(elements);
 
     this._addresses = addresses;
     Object.assign(this, config);
     Object.assign(this._elements, {
       ccNumber: this._elements.form.querySelector("#cc-number"),
       invalidCardNumberStringElement: this._elements.form.querySelector("#invalidCardNumberString"),
       month: this._elements.form.querySelector("#cc-exp-month"),
       year: this._elements.form.querySelector("#cc-exp-year"),
+      ccType: this._elements.form.querySelector("#cc-type"),
       billingAddress: this._elements.form.querySelector("#billingAddressGUID"),
       billingAddressRow: this._elements.form.querySelector(".billingAddressRow"),
     });
 
     this.loadRecord(record, addresses);
     this.attachEventListeners();
   }
 
   loadRecord(record, addresses, preserveFieldValues) {
     // _record must be updated before generateYears and generateBillingAddressOptions are called.
     this._record = record;
     this._addresses = addresses;
     this.generateBillingAddressOptions();
     if (!preserveFieldValues) {
+      // Re-populating the networks will reset the selected option.
+      this.populateNetworks();
       // Re-generating the years will reset the selected option.
       this.generateYears();
       super.loadRecord(record);
 
       // Resetting the form in the super.loadRecord won't clear custom validity
       // state so reset it here. Since the cc-number field is disabled upon editing
       // we don't need to recaclulate its validity here.
       this._elements.ccNumber.setCustomValidity("");
@@ -358,16 +362,33 @@ class EditCreditCard extends EditAutofil
       this._elements.year.appendChild(option);
     }
 
     if (ccExpYear && ccExpYear > currentYear + count) {
       this._elements.year.appendChild(new Option(ccExpYear));
     }
   }
 
+  populateNetworks() {
+    // Clear the list
+    this._elements.ccType.textContent = "";
+    let frag = document.createDocumentFragment();
+    // include an empty first option
+    frag.appendChild(new Option("", ""));
+
+    let supportedNetworks = this.getSupportedNetworks();
+    for (let id of supportedNetworks) {
+      let option = new Option();
+      option.value = id;
+      option.dataset.localization = "cardNetwork." + id;
+      frag.appendChild(option);
+    }
+    this._elements.ccType.appendChild(frag);
+  }
+
   generateBillingAddressOptions() {
     let billingAddressGUID = this._record && this._record.billingAddressGUID;
 
     this._elements.billingAddress.textContent = "";
 
     this._elements.billingAddress.appendChild(new Option("", ""));
 
     let hasAddresses = false;
--- a/browser/extensions/formautofill/content/editAddress.xhtml
+++ b/browser/extensions/formautofill/content/editAddress.xhtml
@@ -17,73 +17,69 @@
   <script src="chrome://formautofill/content/autofillEditForms.js"></script>
 </head>
 <body dir="&locale.dir;">
   <form id="form" class="editAddressForm" autocomplete="off">
     <!--
         The <span class="label-text" …/> needs to be after the form field in the same element in
         order to get proper label styling with :focus and :moz-ui-invalid.
       -->
-    <div>
-      <div id="name-container">
-        <label id="given-name-container">
-          <input id="given-name" type="text" required="required"/>
-          <span data-localization="givenName" class="label-text"/>
-        </label>
-        <label id="additional-name-container">
-          <input id="additional-name" type="text"/>
-          <span data-localization="additionalName" class="label-text"/>
-        </label>
-        <label id="family-name-container">
-          <input id="family-name" type="text" required="required"/>
-          <span data-localization="familyName" class="label-text"/>
-        </label>
-      </div>
-      <label id="organization-container">
-        <input id="organization" type="text"/>
-        <span data-localization="organization2" class="label-text"/>
-      </label>
-      <label id="street-address-container">
-        <textarea id="street-address" rows="3" required="required"/>
-        <span data-localization="streetAddress" class="label-text"/>
+    <div id="name-container" class="container">
+      <label id="given-name-container">
+        <input id="given-name" type="text" required="required"/>
+        <span data-localization="givenName" class="label-text"/>
       </label>
-      <label id="address-level2-container">
-        <input id="address-level2" type="text" required="required"/>
-        <span data-localization="city" class="label-text"/>
-      </label>
-      <label id="address-level1-container">
-        <input id="address-level1" type="text" required="required"/>
-        <span class="label-text"/>
-      </label>
-      <label id="postal-code-container">
-        <input id="postal-code" type="text" required="required"/>
-        <span class="label-text"/>
+      <label id="additional-name-container">
+        <input id="additional-name" type="text"/>
+        <span data-localization="additionalName" class="label-text"/>
       </label>
-      <div id="country-container">
-        <label id="country-label">
-          <select id="country" required="required">
-            <option/>
-          </select>
-          <span data-localization="country" class="label-text"/>
-        </label>
-        <p id="country-warning-message" data-localization="countryWarningMessage2"/>
-      </div>
-      <label id="tel-container">
-        <input id="tel" type="tel"/>
-        <span data-localization="tel" class="label-text"/>
-      </label>
-      <label id="email-container">
-        <input id="email" type="email" required="required"/>
-        <span data-localization="email" class="label-text"/>
+      <label id="family-name-container">
+        <input id="family-name" type="text" required="required"/>
+        <span data-localization="familyName" class="label-text"/>
       </label>
     </div>
+    <label id="organization-container" class="container">
+      <input id="organization" type="text"/>
+      <span data-localization="organization2" class="label-text"/>
+    </label>
+    <label id="street-address-container" class="container">
+      <textarea id="street-address" rows="3" required="required"/>
+      <span data-localization="streetAddress" class="label-text"/>
+    </label>
+    <label id="address-level2-container" class="container">
+      <input id="address-level2" type="text" required="required"/>
+      <span data-localization="city" class="label-text"/>
+    </label>
+    <label id="address-level1-container" class="container">
+      <input id="address-level1" type="text" required="required"/>
+      <span class="label-text"/>
+    </label>
+    <label id="postal-code-container" class="container">
+      <input id="postal-code" type="text" required="required"/>
+      <span class="label-text"/>
+    </label>
+    <label id="country-container" class="container">
+      <select id="country" required="required">
+        <option/>
+      </select>
+      <span data-localization="country" class="label-text"/>
+    </label>
+    <label id="tel-container" class="container">
+      <input id="tel" type="tel"/>
+      <span data-localization="tel" class="label-text"/>
+    </label>
+    <label id="email-container" class="container">
+      <input id="email" type="email" required="required"/>
+      <span data-localization="email" class="label-text"/>
+    </label>
   </form>
   <div id="controls-container">
     <button id="cancel" data-localization="cancelBtnLabel"/>
     <button id="save" disabled="disabled" data-localization="saveBtnLabel"/>
+    <span id="country-warning-message" data-localization="countryWarningMessage2"/>
   </div>
   <script type="application/javascript"><![CDATA[
     "use strict";
 
     let {
       DEFAULT_REGION,
       supportedCountries,
     } = FormAutofill;
--- a/browser/extensions/formautofill/content/editCreditCard.xhtml
+++ b/browser/extensions/formautofill/content/editCreditCard.xhtml
@@ -17,26 +17,22 @@
   <script src="chrome://formautofill/content/autofillEditForms.js"></script>
 </head>
 <body dir="&locale.dir;">
   <form id="form" class="editCreditCardForm" autocomplete="off">
     <!--
         The <span class="label-text" …/> needs to be after the form field in the same element in
         order to get proper label styling with :focus and :moz-ui-invalid.
       -->
-    <label>
+    <label id="cc-number-container" class="container">
       <span id="invalidCardNumberString" hidden="hidden" data-localization="invalidCardNumber"></span>
       <input id="cc-number" type="text" required="required" minlength="9" pattern="[- 0-9]+"/>
       <span data-localization="cardNumber" class="label-text"/>
     </label>
-    <label>
-      <input id="cc-name" type="text" required="required"/>
-      <span data-localization="nameOnCard" class="label-text"/>
-    </label>
-    <label>
+    <label id="cc-exp-month-container" class="container">
       <select id="cc-exp-month">
         <option/>
         <option value="1">01</option>
         <option value="2">02</option>
         <option value="3">03</option>
         <option value="4">04</option>
         <option value="5">05</option>
         <option value="6">06</option>
@@ -44,52 +40,63 @@
         <option value="8">08</option>
         <option value="9">09</option>
         <option value="10">10</option>
         <option value="11">11</option>
         <option value="12">12</option>
       </select>
       <span data-localization="cardExpiresMonth" class="label-text"/>
     </label>
-    <label>
+    <label id="cc-exp-year-container" class="container">
       <select id="cc-exp-year">
         <option/>
       </select>
       <span data-localization="cardExpiresYear" class="label-text"/>
     </label>
-    <label class="billingAddressRow">
+    <label id="cc-name-container" class="container">
+      <input id="cc-name" type="text" required="required"/>
+      <span data-localization="nameOnCard" class="label-text"/>
+    </label>
+    <label id="cc-type-container" class="container">
+      <select id="cc-type">
+      </select>
+      <span data-localization="cardNetwork" class="label-text"/>
+    </label>
+    <label id="billingAddressGUID-container" class="billingAddressRow container">
       <select id="billingAddressGUID">
       </select>
       <span data-localization="billingAddress" class="label-text"/>
     </label>
   </form>
   <div id="controls-container">
     <button id="cancel" data-localization="cancelBtnLabel"/>
     <button id="save" disabled="disabled" data-localization="saveBtnLabel"/>
   </div>
   <script type="application/javascript"><![CDATA[
     "use strict";
 
     let {
       getAddressLabel,
       isCCNumber,
+      getCreditCardNetworks,
     } = FormAutofillUtils;
     let record = window.arguments && window.arguments[0];
     let addresses = {};
     for (let address of formAutofillStorage.addresses.getAll()) {
       addresses[address.guid] = address;
     }
 
     /* import-globals-from autofillEditForms.js */
     let fieldContainer = new EditCreditCard({
       form: document.getElementById("form"),
     }, record, addresses,
       {
         getAddressLabel: getAddressLabel.bind(FormAutofillUtils),
         isCCNumber: isCCNumber.bind(FormAutofillUtils),
+        getSupportedNetworks: getCreditCardNetworks.bind(FormAutofillUtils),
       });
 
     /* import-globals-from editDialog.js */
     new EditCreditCardDialog({
       title: document.querySelector("title"),
       fieldContainer,
       controlsContainer: document.getElementById("controls-container"),
       cancel: document.getElementById("cancel"),
--- a/browser/extensions/formautofill/content/l10n.js
+++ b/browser/extensions/formautofill/content/l10n.js
@@ -31,19 +31,18 @@ CONTENT_WIN.addEventListener("DOMContent
             // The attribute was removed in the meantime.
             continue;
           }
           FormAutofillUtils.localizeAttributeForElement(mutation.target, mutation.attributeName);
           break;
         }
 
         case "childList": {
-          // We really only care about the <form>s appending inside pages.
-          if (!mutation.addedNodes || !mutation.target.classList ||
-              !mutation.target.classList.contains("page")) {
+          // We really only care about elements appending inside pages.
+          if (!mutation.addedNodes || !mutation.target.closest(".page")) {
             break;
           }
           FormAutofillUtils.localizeMarkup(mutation.target);
           break;
         }
       }
     }
   });
--- a/browser/extensions/formautofill/content/manageDialog.js
+++ b/browser/extensions/formautofill/content/manageDialog.js
@@ -341,16 +341,17 @@ class ManageCreditCards extends ManageRe
    * @param {boolean} showCreditCards [optional]
    * @returns {string}
    */
   async getLabel(creditCard, showCreditCards = false) {
     let cardObj = new CreditCard({
       encryptedNumber: creditCard["cc-number-encrypted"],
       number: creditCard["cc-number"],
       name: creditCard["cc-name"],
+      network: creditCard["cc-type"],
     });
     return cardObj.getLabel({showNumbers: showCreditCards});
   }
 
   async toggleShowHideCards(options) {
     this._isDecrypted = !this._isDecrypted;
     this.updateShowHideButtonState();
     await this.updateLabels(options, this._isDecrypted);
--- a/browser/extensions/formautofill/locales/en-US/formautofill.properties
+++ b/browser/extensions/formautofill/locales/en-US/formautofill.properties
@@ -136,8 +136,20 @@ countryWarningMessage2 = Form Autofill i
 addNewCreditCardTitle = Add New Credit Card
 editCreditCardTitle = Edit Credit Card
 cardNumber = Card Number
 invalidCardNumber = Please enter a valid card number
 nameOnCard = Name on Card
 cardExpiresMonth = Exp. Month
 cardExpiresYear = Exp. Year
 billingAddress = Billing Address
+cardNetwork = Card Type
+
+# LOCALIZATION NOTE: (cardNetwork.*): These are brand names and should only be translated when a locale-specific name for that brand is in common use
+cardNetwork.amex = American Express
+cardNetwork.cartebancaire = Carte Bancaire
+cardNetwork.diners = Diners Club
+cardNetwork.discover = Discover
+cardNetwork.jcb = JCB
+cardNetwork.mastercard = MasterCard
+cardNetwork.mir = MIR
+cardNetwork.unionpay = Union Pay
+cardNetwork.visa = Visa
--- a/browser/extensions/formautofill/skin/shared/editAddress.css
+++ b/browser/extensions/formautofill/skin/shared/editAddress.css
@@ -1,36 +1,37 @@
 /* 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/. */
 
-.editAddressForm input,
-.editAddressForm select {
-  flex: 1 0 auto;
-  margin: 0;
+.editAddressForm {
+  display: flex;
+  flex-wrap: wrap;
+  /* Use space-between so --grid-column-row-gap is in between the elements on a row */
+  justify-content: space-between;
 }
 
-#name-container,
-:root[subdialog] form label,
-:root[subdialog] form > p {
-  margin: 0 0 0.5em !important;
+:root:not([subdialog]) .editAddressForm {
+  margin-inline-start: calc(var(--grid-column-row-gap) / -2);
+  margin-inline-end: calc(var(--grid-column-row-gap) / -2);
 }
 
-#given-name-container,
-#additional-name-container,
-#address-level1-container,
-#postal-code-container,
-#country-label,
-#country-warning-message,
-#family-name-container,
-#organization-container,
-#address-level2-container,
-#tel-container {
-  display: flex;
-  flex: 0 1 50%;
+.editAddressForm .container {
+  /* !important is needed to override preferences.css's generic label rule. */
+  margin-top: var(--grid-column-row-gap) !important;
+  margin-inline-start: calc(var(--grid-column-row-gap) / 2);
+  margin-inline-end: calc(var(--grid-column-row-gap) / 2);
+  flex-grow: 1;
+}
+
+#country-container {
+  /* The country dropdown has a different intrinsic (content) width than the
+     other fields which are <input>. */
+  flex-basis: calc(50% - var(--grid-column-row-gap));
+  flex-grow: 0;
 }
 
 
 /* Begin name field rules */
 
 #name-container input {
   /* Override the default @size="20" on <input>, which acts like a min-width, not
    * allowing the fields to shrink with flexbox as small as they need to to match
@@ -49,16 +50,19 @@
 #name-container:focus-within input:-moz-ui-invalid {
   border-color: transparent;
 }
 
 #given-name-container,
 #additional-name-container,
 #family-name-container {
   display: flex;
+  /* The 3 pieces inside the name container don't have the .container class so
+     need to set flex-grow themselves. See `.editAddressForm .container` */
+  flex-grow: 1;
   /* Remove the bottom margin from the name containers so that the outer
      #name-container provides the margin on the outside */
   margin-bottom: 0 !important;
   margin-left: 0;
   margin-right: 0;
 }
 
 /* The name fields are placed adjacent to each other.
@@ -90,29 +94,26 @@
    so the shadow is shown around all 4 sides. */
 #name-container input:-moz-ui-invalid,
 #name-container input:-moz-ui-invalid ~ .label-text {
   z-index: 1;
 }
 
 /* End name field rules */
 
-
 #name-container,
-#street-address-container,
-#country-container,
-#email-container {
+#street-address-container {
+  /* Name and street address are always full-width */
   flex: 0 1 100%;
 }
 
-#street-address,
-#email {
-  flex: 1 0 auto;
-}
-
 #country-warning-message {
   box-sizing: border-box;
   font-size: 1rem;
   align-items: center;
   text-align: start;
   color: #737373;
   padding-inline-start: 1em;
 }
+
+:root:not([subdialog]) #country-warning-message {
+  display: none;
+}
--- a/browser/extensions/formautofill/skin/shared/editCreditCard.css
+++ b/browser/extensions/formautofill/skin/shared/editCreditCard.css
@@ -1,29 +1,48 @@
 /* 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/. */
 
 .editCreditCardForm {
-  justify-content: center;
+  display: grid;
+  grid-template-areas:
+    "cc-number          cc-exp-month       cc-exp-year"
+    "cc-name            cc-type            cc-csc"
+    "billingAddressGUID billingAddressGUID billingAddressGUID";
+  grid-row-gap: var(--grid-column-row-gap);
+  grid-column-gap: var(--grid-column-row-gap);
 }
 
-.editCreditCardForm > label,
-.editCreditCardForm > div {
-  flex: 1 0 100%;
-  align-self: center;
-  margin: 0 0 0.5em !important;
+.editCreditCardForm label {
+  /* Remove the margin on these labels since they are styled on top of
+     the input/select element. */
+  margin-inline-start: 0;
+  margin-inline-end: 0;
+}
+
+.editCreditCardForm .container {
+  display: flex;
 }
 
-.editCreditCardForm #billingAddressGUID,
-.editCreditCardForm input {
-  flex: 1 0 auto;
+#cc-number-container {
+  grid-area: cc-number;
+}
+
+#cc-exp-month-container {
+  grid-area: cc-exp-month;
+}
+
+#cc-exp-year-container {
+  grid-area: cc-exp-year;
 }
 
-.editCreditCardForm select {
-  margin: 0;
-  margin-inline-end: 0.7em;
+#cc-name-container {
+  grid-area: cc-name;
 }
 
-.editCreditCardForm label > span,
-.editCreditCardForm div > span {
-  flex: 0 0 9.5em;
+#cc-type-container {
+  grid-area: cc-type;
 }
+
+#billingAddressGUID-container {
+  grid-area: billingAddressGUID;
+}
--- a/browser/extensions/formautofill/skin/shared/editDialog-shared.css
+++ b/browser/extensions/formautofill/skin/shared/editDialog-shared.css
@@ -1,42 +1,46 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :root {
   --in-field-label-size: .8em;
+  --grid-column-row-gap: 8px;
   /* Use the animation-easing-function that is defined in xul.css. */
   --animation-easing-function: cubic-bezier(.07,.95,0,1);
 }
 
 :root[subdialog] form {
   /* Add extra space to ensure invalid input box is displayed properly */
   padding: 2px;
 }
 
+/* The overly specific input attributes are required to override
+   padding from common.css */
 form input[type="email"],
 form input[type="tel"],
 form input[type="text"],
 form textarea,
 form select {
+  flex-grow: 1;
   padding-top: calc(var(--in-field-label-size) + .4em);
 }
 
 select {
   margin: 0;
   padding-bottom: 5px;
 }
 
 form :-moz-any(label, div) {
+  /* Positioned so that the .label-text and .error-text children will be
+     positioned relative to this. */
   position: relative;
   display: block;
   line-height: 1em;
-  margin-left: 0;
-  margin-right: 0;
 }
 
 form :-moz-any(label, div) > .label-text {
   position: absolute;
   color: GrayText;
   pointer-events: none;
   left: 10px;
   top: .2em;
@@ -60,13 +64,28 @@ form :-moz-any(input, select, textarea):
   color: var(--in-content-text-color);
 }
 
 form div[required] > label > .label-text::after,
 form :-moz-any(label, div)[required] > .label-text::after {
   content: attr(fieldRequiredSymbol);
 }
 
+.persist-checkbox label {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-top: var(--grid-column-row-gap);
+  margin-bottom: var(--grid-column-row-gap);
+}
+
+:root[subdialog] form {
+  /* Match the margin-inline-start of the #controls-container buttons
+     and provide enough padding at the top of the form so button outlines
+     don't get clipped. */
+  padding: 4px 4px 0;
+}
+
 #controls-container {
   flex: 0 1 100%;
   justify-content: end;
   margin: 1em 0 0;
 }
--- a/browser/extensions/formautofill/test/browser/browser_creditCard_doorhanger.js
+++ b/browser/extensions/formautofill/test/browser/browser_creditCard_doorhanger.js
@@ -55,30 +55,32 @@ add_task(async function test_submit_cred
         let form = content.document.getElementById("form");
         let name = form.querySelector("#cc-name");
         name.focus();
         name.setUserInput("User 1");
 
         form.querySelector("#cc-number").setUserInput("5038146897157463");
         form.querySelector("#cc-exp-month").setUserInput("12");
         form.querySelector("#cc-exp-year").setUserInput("2017");
+        form.querySelector("#cc-type").value = "mastercard";
 
         // Wait 1000ms before submission to make sure the input value applied
         await new Promise(resolve => setTimeout(resolve, 1000));
         form.querySelector("input[type=submit]").click();
       });
 
       await promiseShown;
       await clickDoorhangerButton(MAIN_BUTTON);
     }
   );
 
   let creditCards = await getCreditCards();
   is(creditCards.length, 1, "1 credit card in storage");
   is(creditCards[0]["cc-name"], "User 1", "Verify the name field");
+  is(creditCards[0]["cc-type"], "mastercard", "Verify the cc-type field");
   is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
   SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
   await removeAllRecords();
 });
 
 add_task(async function test_submit_untouched_creditCard_form() {
   await SpecialPowers.pushPrefEnv({
     "set": [
@@ -171,16 +173,17 @@ add_task(async function test_submit_dupl
         let form = content.document.getElementById("form");
         let name = form.querySelector("#cc-name");
         name.focus();
 
         name.setUserInput("John Doe");
         form.querySelector("#cc-number").setUserInput("4111111111111111");
         form.querySelector("#cc-exp-month").setUserInput("4");
         form.querySelector("#cc-exp-year").setUserInput(new Date().getFullYear());
+        form.querySelector("#cc-type").value = "visa";
 
         // Wait 1000ms before submission to make sure the input value applied
         await new Promise(resolve => setTimeout(resolve, 1000));
         form.querySelector("input[type=submit]").click();
       });
 
       await sleep(1000);
       is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden");
@@ -208,16 +211,17 @@ add_task(async function test_submit_unno
         let name = form.querySelector("#cc-name");
         name.focus();
 
         name.setUserInput("John Doe");
         form.querySelector("#cc-number").setUserInput("4111111111111111");
         form.querySelector("#cc-exp-month").setUserInput("4");
         // Set unnormalized year
         form.querySelector("#cc-exp-year").setUserInput(new Date().getFullYear().toString().substr(2, 2));
+        form.querySelector("#cc-type").value = "visa";
 
         // Wait 1000ms before submission to make sure the input value applied
         await new Promise(resolve => setTimeout(resolve, 1000));
         form.querySelector("input[type=submit]").click();
       });
 
       await sleep(1000);
       is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden");
@@ -631,8 +635,44 @@ add_task(async function test_update_dupl
 
   creditCards = await getCreditCards();
   is(creditCards.length, 2, "Still 2 credit card");
   is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 1,
     "User neither sees the doorhanger nor uses autofill but somehow has a record in the storage");
   SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
   await removeAllRecords();
 });
+
+add_task(async function test_submit_creditCard_with_invalid_network() {
+  await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
+    async function(browser) {
+      let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
+                                                       "popupshown");
+      await ContentTask.spawn(browser, null, async function() {
+        let form = content.document.getElementById("form");
+        let name = form.querySelector("#cc-name");
+        name.focus();
+        name.setUserInput("User 1");
+
+        form.querySelector("#cc-number").setUserInput("5038146897157463");
+        form.querySelector("#cc-exp-month").setUserInput("12");
+        form.querySelector("#cc-exp-year").setUserInput("2017");
+        form.querySelector("#cc-type").value = "gringotts";
+
+        // Wait 1000ms before submission to make sure the input value applied
+        await new Promise(resolve => setTimeout(resolve, 1000));
+        form.querySelector("input[type=submit]").click();
+      });
+
+      await promiseShown;
+      await clickDoorhangerButton(MAIN_BUTTON);
+    }
+  );
+
+  let creditCards = await getCreditCards();
+  is(creditCards.length, 1, "1 credit card in storage");
+  is(creditCards[0]["cc-name"], "User 1", "Verify the name field");
+  is(creditCards[0]["cc-type"], undefined, "Invalid network/cc-type was not saved");
+
+  SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
+  await removeAllRecords();
+});
+
--- a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
+++ b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
@@ -57,26 +57,26 @@ add_task(async function test_saveAddress
     const keyInputs = [
       "VK_TAB",
       TEST_ADDRESS_1["given-name"],
       "VK_TAB",
       TEST_ADDRESS_1["additional-name"],
       "VK_TAB",
       TEST_ADDRESS_1["family-name"],
       "VK_TAB",
-      TEST_ADDRESS_1.organization,
-      "VK_TAB",
       TEST_ADDRESS_1["street-address"],
       "VK_TAB",
       TEST_ADDRESS_1["address-level2"],
       "VK_TAB",
       TEST_ADDRESS_1["address-level1"],
       "VK_TAB",
       TEST_ADDRESS_1["postal-code"],
       "VK_TAB",
+      TEST_ADDRESS_1.organization,
+      "VK_TAB",
       TEST_ADDRESS_1.country,
       "VK_TAB",
       TEST_ADDRESS_1.tel,
       "VK_TAB",
       TEST_ADDRESS_1.email,
       "VK_TAB",
       "VK_TAB",
       "VK_RETURN",
--- a/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js
+++ b/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js
@@ -19,22 +19,24 @@ add_task(async function test_cancelEditC
   });
 });
 
 add_task(async function test_saveCreditCard() {
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-number"], {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
-    EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-name"], {}, win);
-    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("0" + TEST_CREDIT_CARD_1["cc-exp-month"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-exp-year"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-name"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-type"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     info("saving credit card");
     EventUtils.synthesizeKey("VK_RETURN", {}, win);
   });
   let creditCards = await getCreditCards();
 
   is(creditCards.length, 1, "only one credit card is in storage");
@@ -48,22 +50,24 @@ add_task(async function test_saveCreditC
   ok(creditCards[0]["cc-number-encrypted"], "cc-number-encrypted exists");
 });
 
 add_task(async function test_saveCreditCardWithMaxYear() {
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-number"], {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
-    EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-name"], {}, win);
-    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-exp-month"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-exp-year"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-name"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-type"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     info("saving credit card");
     EventUtils.synthesizeKey("VK_RETURN", {}, win);
   });
   let creditCards = await getCreditCards();
 
   is(creditCards.length, 2, "Two credit cards are in storage");
@@ -86,22 +90,24 @@ add_task(async function test_saveCreditC
   const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_2, {
     billingAddressGUID: billingAddress.guid,
   });
 
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-number"], {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
-    EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-name"], {}, win);
-    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-exp-month"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-exp-year"].toString(), {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-name"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-type"], {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey(billingAddress["given-name"], {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     info("saving credit card");
     EventUtils.synthesizeKey("VK_RETURN", {}, win);
   });
   let creditCards = await getCreditCards();
 
@@ -122,16 +128,18 @@ add_task(async function test_saveCreditC
 });
 
 add_task(async function test_editCreditCard() {
   let creditCards = await getCreditCards();
   is(creditCards.length, 1, "only one credit card is in storage");
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_RIGHT", {}, win);
     EventUtils.synthesizeKey("test", {}, win);
     win.document.querySelector("#save").click();
   }, creditCards[0]);
   ok(true, "Edit credit card dialog is closed");
   creditCards = await getCreditCards();
 
   is(creditCards.length, 1, "only one credit card is in storage");
@@ -150,16 +158,18 @@ add_task(async function test_editCreditC
 
   let creditCards = await getCreditCards();
   is(creditCards.length, 1, "one credit card in storage");
   is(creditCards[0].billingAddressGUID, TEST_CREDIT_CARD.billingAddressGUID,
      "Check saved billingAddressGUID");
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("VK_RIGHT", {}, win);
     EventUtils.synthesizeKey("test", {}, win);
     win.document.querySelector("#save").click();
   }, creditCards[0]);
   ok(true, "Edit credit card dialog is closed");
   creditCards = await getCreditCards();
 
   is(creditCards.length, 1, "only one credit card is in storage");
@@ -175,16 +185,18 @@ add_task(async function test_editCreditC
 add_task(async function test_addInvalidCreditCard() {
   await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
     const unloadHandler = () => ok(false, "Edit credit card dialog shouldn't be closed");
     win.addEventListener("unload", unloadHandler);
 
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("test", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeKey("test name", {}, win);
     EventUtils.synthesizeKey("VK_TAB", {}, win);
     EventUtils.synthesizeMouseAtCenter(win.document.querySelector("#save"), {}, win);
 
     is(win.document.querySelector("form").checkValidity(), false, "cc-number is invalid");
     SimpleTest.requestFlakyTimeout("Ensure the window remains open after save attempt");
     setTimeout(() => {
       win.removeEventListener("unload", unloadHandler);
@@ -192,8 +204,40 @@ add_task(async function test_addInvalidC
       win.close();
     }, 500);
   });
   info("closed");
   let creditCards = await getCreditCards();
 
   is(creditCards.length, 0, "Credit card storage is empty");
 });
+
+add_task(async function test_editCardWithInvalidNetwork() {
+  const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_2, {
+    "cc-type": "asiv",
+  });
+  await saveCreditCard(TEST_CREDIT_CARD);
+
+  let creditCards = await getCreditCards();
+  is(creditCards.length, 1, "one credit card in storage");
+  is(creditCards[0]["cc-type"], TEST_CREDIT_CARD["cc-type"],
+     "Check saved cc-type");
+  await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, (win) => {
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_TAB", {}, win);
+    EventUtils.synthesizeKey("VK_RIGHT", {}, win);
+    EventUtils.synthesizeKey("test", {}, win);
+    win.document.querySelector("#save").click();
+  }, creditCards[0]);
+  ok(true, "Edit credit card dialog is closed");
+  creditCards = await getCreditCards();
+
+  is(creditCards.length, 1, "only one credit card is in storage");
+  is(creditCards[0]["cc-name"], TEST_CREDIT_CARD["cc-name"] + "test", "cc name changed");
+  is(creditCards[0]["cc-type"], undefined,
+     "unknown cc-type removed upon manual save");
+  await removeCreditCards([creditCards[0].guid]);
+
+  creditCards = await getCreditCards();
+  is(creditCards.length, 0, "Credit card storage is empty");
+});
--- a/browser/extensions/formautofill/test/browser/head.js
+++ b/browser/extensions/formautofill/test/browser/head.js
@@ -99,29 +99,32 @@ const TEST_ADDRESS_DE_1 = {
   email: "timbl@w3.org",
 };
 
 const TEST_CREDIT_CARD_1 = {
   "cc-name": "John Doe",
   "cc-number": "4111111111111111",
   "cc-exp-month": 4,
   "cc-exp-year": new Date().getFullYear(),
+  "cc-type": "visa",
 };
 
 const TEST_CREDIT_CARD_2 = {
   "cc-name": "Timothy Berners-Lee",
   "cc-number": "4929001587121045",
   "cc-exp-month": 12,
   "cc-exp-year": new Date().getFullYear() + 10,
+  "cc-type": "visa",
 };
 
 const TEST_CREDIT_CARD_3 = {
   "cc-number": "5103059495477870",
   "cc-exp-month": 1,
   "cc-exp-year": 2000,
+  "cc-type": "mastercard",
 };
 
 const MAIN_BUTTON = "button";
 const SECONDARY_BUTTON = "secondaryButton";
 const MENU_BUTTON = "menubutton";
 
 function getDisplayedPopupItems(browser, selector = ".autocomplete-richlistitem") {
   info("getDisplayedPopupItems");
--- a/browser/extensions/formautofill/test/fixtures/autocomplete_creditcard_basic.html
+++ b/browser/extensions/formautofill/test/fixtures/autocomplete_creditcard_basic.html
@@ -7,15 +7,23 @@
 <body>
   <h1>Form Autofill Credit Card Demo Page</h1>
   <form id="form">
     <p><label>Name: <input id="cc-name" autocomplete="cc-name"></label></p>
     <p><label>Card Number: <input id="cc-number" autocomplete="cc-number"></label></p>
     <p><label>Expiration month: <input id="cc-exp-month" autocomplete="cc-exp-month"></label></p>
     <p><label>Expiration year: <input id="cc-exp-year" autocomplete="cc-exp-year"></label></p>
     <p><label>CSC: <input id="cc-csc" autocomplete="cc-csc"></label></p>
+    <p><label>Card Type: <select id="cc-type" autocomplete="cc-type">
+      <option></option>
+      <option value="discover">Discover</option>
+      <option value="jcb">JCB</option>
+      <option value="visa">Visa</option>
+      <option value="mastercard">MasterCard</option>
+      <option value="gringotts">Unknown card network</option>
+    </select></label></p>
     <p>
       <input type="submit" value="Submit">
       <button type="reset">Reset</button>
     </p>
   </form>
 </body>
 </html>
--- a/browser/extensions/formautofill/test/mochitest/test_basic_creditcard_autocomplete_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_basic_creditcard_autocomplete_form.html
@@ -18,21 +18,23 @@ Form autofill test: simple form credit c
 
 "use strict";
 
 const MOCK_STORAGE = [{
   "cc-name": "John Doe",
   "cc-number": "4929001587121045",
   "cc-exp-month": 4,
   "cc-exp-year": 2017,
+  "cc-type": "visa",
 }, {
   "cc-name": "Timothy Berners-Lee",
   "cc-number": "5103059495477870",
   "cc-exp-month": 12,
   "cc-exp-year": 2022,
+  "cc-type": "mastercard",
 }];
 
 const reducedMockRecord = {
   "cc-name": "John Doe",
   "cc-number": "4929001587121045",
 };
 
 async function setupCreditCardStorage() {
@@ -192,15 +194,21 @@ add_task(async function check_form_autof
 <div id="content">
 
   <form id="form1">
     <p>This is a basic form.</p>
     <p><label>Name: <input id="cc-name" autocomplete="cc-name"></label></p>
     <p><label>Card Number: <input id="cc-number" autocomplete="cc-number"></label></p>
     <p><label>Expiration month: <input id="cc-exp-month" autocomplete="cc-exp-month"></label></p>
     <p><label>Expiration year: <input id="cc-exp-year" autocomplete="cc-exp-year"></label></p>
+    <p><label>Card Type: <select id="cc-type" autocomplete="cc-type">
+      <option value="discover">Discover</option>
+      <option value="jcb">JCB</option>
+      <option value="visa">Visa</option>
+      <option value="mastercard">MasterCard</option>
+    </select></label></p>
     <p><label>CSC: <input id="cc-csc" autocomplete="cc-csc"></label></p>
   </form>
 </div>
 
 <pre id="test"></pre>
 </body>
 </html>
--- a/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
@@ -16,23 +16,25 @@ add_task(async function setup() {
 const TEST_STORE_FILE_NAME = "test-credit-card.json";
 const COLLECTION_NAME = "creditCards";
 
 const TEST_CREDIT_CARD_1 = {
   "cc-name": "John Doe",
   "cc-number": "4929001587121045",
   "cc-exp-month": 4,
   "cc-exp-year": 2017,
+  "cc-type": "visa",
 };
 
 const TEST_CREDIT_CARD_2 = {
   "cc-name": "Timothy Berners-Lee",
   "cc-number": "5103059495477870",
   "cc-exp-month": 12,
   "cc-exp-year": 2022,
+  "cc-type": "mastercard",
 };
 
 const TEST_CREDIT_CARD_3 = {
   "cc-number": "3589993783099582",
   "cc-exp-month": 1,
   "cc-exp-year": 2000,
 };
 
@@ -47,16 +49,17 @@ const TEST_CREDIT_CARD_WITH_BILLING_ADDR
   billingAddressGUID: "9m6hf4gfr6ge",
 };
 
 const TEST_CREDIT_CARD_WITH_EMPTY_FIELD = {
   billingAddressGUID: "",
   "cc-name": "",
   "cc-number": "344060747836806",
   "cc-exp-month": 1,
+  "cc-type": "",
 };
 
 const TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD = {
   "cc-given-name": "",
   "cc-additional-name": "",
   "cc-family-name": "",
   "cc-exp": "",
   "cc-number": "5415425865751454",
@@ -81,16 +84,24 @@ const TEST_CREDIT_CARD_WITH_INVALID_EXPI
   "cc-exp-year": -3,
 };
 
 const TEST_CREDIT_CARD_WITH_SPACES_BETWEEN_DIGITS = {
   "cc-name": "John Doe",
   "cc-number": "5103 0594 9547 7870",
 };
 
+const TEST_CREDIT_CARD_WITH_INVALID_NETWORK = {
+  "cc-name": "John Doe",
+  "cc-number": "4929001587121045",
+  "cc-exp-month": 4,
+  "cc-exp-year": 2017,
+  "cc-type": "asiv",
+};
+
 const TEST_CREDIT_CARD_EMPTY_AFTER_NORMALIZE = {
   "cc-exp-month": 13,
 };
 
 const TEST_CREDIT_CARD_EMPTY_AFTER_UPDATE_CREDIT_CARD_1 = {
   "cc-name": "",
   "cc-number": "",
   "cc-exp-month": 13,
@@ -393,16 +404,17 @@ add_task(async function test_update() {
   Assert.notEqual(creditCard.timeLastModified, timeLastModified);
   do_check_credit_card_matches(creditCard, TEST_CREDIT_CARD_3);
 
   // Empty string should be deleted while updating.
   profileStorage.creditCards.update(profileStorage.creditCards._data[0].guid, TEST_CREDIT_CARD_WITH_EMPTY_FIELD);
   creditCard = profileStorage.creditCards._data[0];
   Assert.equal(creditCard["cc-exp-month"], TEST_CREDIT_CARD_WITH_EMPTY_FIELD["cc-exp-month"]);
   Assert.equal(creditCard["cc-name"], undefined);
+  Assert.equal(creditCard["cc-type"], undefined);
   Assert.equal(creditCard.billingAddressGUID, undefined);
 
   // Empty computed fields shouldn't cause any problem.
   profileStorage.creditCards.update(profileStorage.creditCards._data[0].guid, TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD, false);
   creditCard = profileStorage.creditCards._data[0];
   Assert.equal(creditCard["cc-number"],
     CreditCard.getLongMaskedNumber(TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD["cc-number"]));
   profileStorage.creditCards.update(profileStorage.creditCards._data[1].guid, TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD, true);
@@ -441,30 +453,35 @@ add_task(async function test_validate() 
   let path = getTempFile(TEST_STORE_FILE_NAME).path;
 
   let profileStorage = new FormAutofillStorage(path);
   await profileStorage.initialize();
 
   profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_INVALID_EXPIRY_DATE);
   profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR);
   profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_SPACES_BETWEEN_DIGITS);
+  profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_INVALID_NETWORK);
 
   let creditCards = profileStorage.creditCards.getAll();
 
   Assert.equal(creditCards[0]["cc-exp-month"], undefined);
   Assert.equal(creditCards[0]["cc-exp-year"], undefined);
   Assert.equal(creditCards[0]["cc-exp"], undefined);
 
   let month = TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR["cc-exp-month"];
   let year = parseInt(TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR["cc-exp-year"], 10) + 2000;
   Assert.equal(creditCards[1]["cc-exp-month"], month);
   Assert.equal(creditCards[1]["cc-exp-year"], year);
   Assert.equal(creditCards[1]["cc-exp"], year + "-" + month.toString().padStart(2, "0"));
 
   Assert.equal(creditCards[2]["cc-number"].length, 16);
+
+  // dont enforce validity on the card network when storing a record,
+  // to avoid data loss when syncing records between different clients with different rules
+  Assert.equal(creditCards[3]["cc-type"], "asiv");
 });
 
 add_task(async function test_notifyUsed() {
   let path = getTempFile(TEST_STORE_FILE_NAME).path;
   await prepareTestCreditCards(path);
 
   let profileStorage = new FormAutofillStorage(path);
   await profileStorage.initialize();
--- a/browser/extensions/formautofill/test/unit/test_getRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_getRecords.js
@@ -31,23 +31,25 @@ const TEST_ADDRESS_2 = {
   country: "US",
 };
 
 let TEST_CREDIT_CARD_1 = {
   "cc-name": "John Doe",
   "cc-number": "4111111111111111",
   "cc-exp-month": 4,
   "cc-exp-year": 2017,
+  "cc-type": "visa",
 };
 
 let TEST_CREDIT_CARD_2 = {
   "cc-name": "John Dai",
   "cc-number": "4929001587121045",
   "cc-exp-month": 2,
   "cc-exp-year": 2017,
+  "cc-type": "visa",
 };
 
 let target = {
   sendAsyncMessage: function sendAsyncMessage(msg, payload) {},
 };
 
 add_task(async function test_getRecords() {
   let formAutofillParent = new FormAutofillParent();
--- a/browser/extensions/pdfjs/content/PdfJs.jsm
+++ b/browser/extensions/pdfjs/content/PdfJs.jsm
@@ -187,19 +187,17 @@ var PdfJs = {
     }
 
     if (!types.includes(PDF_CONTENT_TYPE)) {
       types.push(PDF_CONTENT_TYPE);
     }
     prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(","));
 
     // Update the category manager in case the plugins are already loaded.
-    let categoryManager = Cc["@mozilla.org/categorymanager;1"];
-    categoryManager.getService(Ci.nsICategoryManager).
-                    deleteCategoryEntry("Gecko-Content-Viewers",
+    Services.catMan.deleteCategoryEntry("Gecko-Content-Viewers",
                                         PDF_CONTENT_TYPE,
                                         false);
   },
 
   _isEnabled: function _isEnabled() {
     var disabled = getBoolPref(PREF_DISABLED, true);
     if (disabled) {
       return false;
--- a/build/mozconfig.no-compile
+++ b/build/mozconfig.no-compile
@@ -18,10 +18,11 @@ unset RUSTDOC
 unset RUSTFMT
 unset CBINDGEN
 unset MAKECAB
 unset TOOLCHAIN_PREFIX
 unset BINDGEN_CFLAGS
 unset LLVM_CONFIG
 unset WIN64_LINK
 unset WIN64_LIB
+unset ENABLE_CLANG_PLUGIN
 
 unset MOZ_STDCXX_COMPAT
--- a/build/unix/mozconfig.linux
+++ b/build/unix/mozconfig.linux
@@ -8,15 +8,16 @@ fi
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
 if [ -n "$FORCE_GCC" -o -n "$MOZ_PGO" ]; then
     CC="$TOOLTOOL_DIR/gcc/bin/gcc"
     CXX="$TOOLTOOL_DIR/gcc/bin/g++"
 else
     CC="$TOOLTOOL_DIR/clang/bin/clang"
     CXX="$TOOLTOOL_DIR/clang/bin/clang++"
+    export ENABLE_CLANG_PLUGIN=1
 fi
 
 # We want to make sure we use binutils and other binaries in the tooltool
 # package.
 mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
 
 . "$topsrcdir/build/unix/mozconfig.stdcxx"
--- a/build/unix/mozconfig.linux32
+++ b/build/unix/mozconfig.linux32
@@ -1,9 +1,15 @@
 . "$topsrcdir/build/unix/mozconfig.linux"
 
 export MOZ_LINUX_32_SSE2_STARTUP_ERROR=1
 
 CFLAGS="$CFLAGS -march=pentium-m -msse -msse2 -mfpmath=sse"
 CXXFLAGS="$CXXFLAGS -march=pentium-m -msse -msse2 -mfpmath=sse"
 
 ac_add_options --target=i686-pc-linux
-ac_add_options --host=i686-pc-linux
+
+# The linux32 builds are effectively cross-compilations, and geckodriver
+# is not enabled by default on cross-compilations, because in most cases,
+# the target is not something we can run binaries of, and geckodriver
+# is a target binary instead of a host binary. But for linux32, we actually
+# can run the target binaries, so we can manually enable geckodriver.
+ac_add_options --enable-geckodriver
--- a/chrome/test/unit/test_abi.js
+++ b/chrome/test/unit/test_abi.js
@@ -1,24 +1,22 @@
+ChromeUtils.import("resource://gre/modules/Services.jsm", this);
 ChromeUtils.import("resource://testing-common/AppInfo.jsm", this);
 updateAppInfo({
   name: "XPCShell",
   ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}",
   version: "5",
   platformVersion: "1.9",
 });
 
 registerManifests([do_get_file("data/test_abi.manifest")]);
 
-const catman = Cc["@mozilla.org/categorymanager;1"].
-  getService(Ci.nsICategoryManager);
-
 function is_registered(name) {
   try {
-    var d = catman.getCategoryEntry("abitest", name);
+    var d = Services.catMan.getCategoryEntry("abitest", name);
     return d == "found";
   } catch (e) {
     return false;
   }
 }
 
 function run_test() {
   Assert.ok(is_registered("test1"));
--- a/devtools/client/inspector/animation/components/PauseResumeButton.js
+++ b/devtools/client/inspector/animation/components/PauseResumeButton.js
@@ -1,18 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { PureComponent } = require("devtools/client/shared/vendor/react");
+const { createRef, PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
-const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 
 const { KeyCodes } = require("devtools/client/shared/keycodes");
 
 const { getStr } = require("../utils/l10n");
 const { hasRunningAnimation } = require("../utils/utils");
 
 class PauseResumeButton extends PureComponent {
   static get propTypes() {
@@ -21,73 +20,77 @@ class PauseResumeButton extends PureComp
       setAnimationsPlayState: PropTypes.func.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.onKeyDown = this.onKeyDown.bind(this);
+    this.pauseResumeButtonRef = createRef();
 
     this.state = {
       isRunning: false,
     };
   }
 
   componentWillMount() {
     this.updateState(this.props);
   }
 
   componentDidMount() {
     const targetEl = this.getKeyEventTarget();
     targetEl.addEventListener("keydown", this.onKeyDown);
   }
 
-  componentWillReceiveProps(nextProps) {
-    this.updateState(nextProps);
+  componentDidUpdate() {
+    this.updateState();
   }
 
   componentWillUnount() {
     const targetEl = this.getKeyEventTarget();
     targetEl.removeEventListener("keydown", this.onKeyDown);
   }
 
   getKeyEventTarget() {
-    return ReactDOM.findDOMNode(this).closest("#animation-container");
+    return this.pauseResumeButtonRef.current.closest("#animation-container");
   }
 
   onToggleAnimationsPlayState(event) {
     event.stopPropagation();
     const { setAnimationsPlayState } = this.props;
     const { isRunning } = this.state;
 
     setAnimationsPlayState(!isRunning);
   }
 
   onKeyDown(event) {
-    if (event.keyCode === KeyCodes.DOM_VK_SPACE) {
+    // Prevent to the duplicated call from the key listener and click listener.
+    if (event.keyCode === KeyCodes.DOM_VK_SPACE &&
+        event.target !== this.pauseResumeButtonRef.current) {
       this.onToggleAnimationsPlayState(event);
     }
   }
 
-  updateState(props) {
-    const { animations } = props;
+  updateState() {
+    const { animations } = this.props;
     const isRunning = hasRunningAnimation(animations);
     this.setState({ isRunning });
   }
 
   render() {
     const { isRunning } = this.state;
 
     return dom.button(
       {
         className: "pause-resume-button devtools-button" +
                    (isRunning ? "" : " paused"),
         onClick: this.onToggleAnimationsPlayState.bind(this),
         title: isRunning ?
                  getStr("timeline.resumedButtonTooltip") :
                  getStr("timeline.pausedButtonTooltip"),
+        ref: this.pauseResumeButtonRef,
       }
     );
   }
 }
 
 module.exports = PauseResumeButton;
--- a/devtools/client/inspector/animation/test/browser_animation_logic_auto-stop.js
+++ b/devtools/client/inspector/animation/test/browser_animation_logic_auto-stop.js
@@ -46,19 +46,19 @@ async function assertStates(animationIns
 
   if (shouldRunning) {
     isnot(previousLabelContent, currentLabelContent,
       "Current time label content should change");
     isnot(previousScrubberX, currentScrubberX,
       "Current time scrubber position should change");
     ok(!buttonEl.classList.contains("paused"),
       "State of button should be running");
-    assertAnimationsRunning(animationInspector, panel);
+    assertAnimationsRunning(animationInspector);
   } else {
     is(previousLabelContent, currentLabelContent,
       "Current time label Content should not change");
     is(previousScrubberX, currentScrubberX,
       "Current time scrubber position should not change");
     ok(buttonEl.classList.contains("paused"),
       "State of button should be paused");
-    assertAnimationsPausing(animationInspector, panel);
+    assertAnimationsPausing(animationInspector);
   }
 }
--- a/devtools/client/inspector/animation/test/browser_animation_pause-resume-button.js
+++ b/devtools/client/inspector/animation/test/browser_animation_pause-resume-button.js
@@ -18,16 +18,16 @@ add_task(async function() {
   const buttonEl = panel.querySelector(".pause-resume-button");
   ok(buttonEl, "pause/resume button should exist");
 
   info("Checking state during running animations");
   ok(!buttonEl.classList.contains("paused"), "State of button should be running");
 
   info("Checking button makes animations to pause");
   await clickOnPauseResumeButton(animationInspector, panel);
-  assertAnimationsPausing(animationInspector, panel);
+  assertAnimationsPausing(animationInspector);
   ok(buttonEl.classList.contains("paused"), "State of button should be paused");
 
   info("Checking button makes animations to resume");
   await clickOnPauseResumeButton(animationInspector, panel);
-  assertAnimationsRunning(animationInspector, panel);
+  assertAnimationsRunning(animationInspector);
   ok(!buttonEl.classList.contains("paused"), "State of button should be resumed");
 });
--- a/devtools/client/inspector/animation/test/browser_animation_pause-resume-button_spacebar.js
+++ b/devtools/client/inspector/animation/test/browser_animation_pause-resume-button_spacebar.js
@@ -7,27 +7,35 @@
 // * make animations to pause/resume by spacebar
 // * combination with other UI components
 
 add_task(async function() {
   await addTab(URL_ROOT + "doc_custom_playback_rate.html");
   const { animationInspector, panel } = await openAnimationInspector();
 
   info("Checking spacebar makes animations to pause");
-  await sendSpaceKeyEvent(animationInspector, panel);
-  assertAnimationsPausing(animationInspector, panel);
-  await sendSpaceKeyEvent(animationInspector, panel);
-  assertAnimationsRunning(animationInspector, panel);
+  await testPauseAndResumeBySpacebar(animationInspector, panel);
+
+  info("Checking spacebar makes animations to pause when the button has the focus");
+  const pauseResumeButton = panel.querySelector(".pause-resume-button");
+  await testPauseAndResumeBySpacebar(animationInspector, pauseResumeButton);
 
   info("Checking spacebar works with other UI components");
   // To pause
   await clickOnPauseResumeButton(animationInspector, panel);
   // To resume
   await sendSpaceKeyEvent(animationInspector, panel);
-  assertAnimationsRunning(animationInspector, panel);
+  assertAnimationsRunning(animationInspector);
   // To pause
   await clickOnCurrentTimeScrubberController(animationInspector, panel, 0.5);
   // To resume
   await clickOnPauseResumeButton(animationInspector, panel);
   // To pause
   await sendSpaceKeyEvent(animationInspector, panel);
-  assertAnimationsPausing(animationInspector, panel);
+  assertAnimationsPausing(animationInspector);
 });
+
+async function testPauseAndResumeBySpacebar(animationInspector, element) {
+  await sendSpaceKeyEvent(animationInspector, element);
+  assertAnimationsPausing(animationInspector);
+  await sendSpaceKeyEvent(animationInspector, element);
+  assertAnimationsRunning(animationInspector);
+}
--- a/devtools/client/inspector/animation/test/browser_animation_rewind-button.js
+++ b/devtools/client/inspector/animation/test/browser_animation_rewind-button.js
@@ -17,16 +17,16 @@ add_task(async function() {
   const { animationInspector, panel } = await openAnimationInspector();
 
   info("Checking button existence");
   ok(panel.querySelector(".rewind-button"), "Rewind button should exist");
 
   info("Checking rewind button makes animations to rewind to zero");
   await clickOnRewindButton(animationInspector, panel);
   assertAnimationsCurrentTime(animationInspector, 0);
-  assertAnimationsPausing(animationInspector, panel);
+  assertAnimationsPausing(animationInspector);
 
   info("Checking rewind button makes animations after clicking scrubber");
   await clickOnCurrentTimeScrubberController(animationInspector, panel, 0.5);
   await clickOnRewindButton(animationInspector, panel);
   assertAnimationsCurrentTime(animationInspector, 0);
-  assertAnimationsPausing(animationInspector, panel);
+  assertAnimationsPausing(animationInspector);
 });
--- a/devtools/client/inspector/animation/test/head.js
+++ b/devtools/client/inspector/animation/test/head.js
@@ -436,22 +436,21 @@ const selectNodeAndWaitForAnimations = a
   await onUpdated;
   await waitForRendering(inspector.animationinspector);
 };
 
 /**
  * Send keyboard event of space to given panel.
  *
  * @param {AnimationInspector} animationInspector
- * @param {DOMElement} panel
- *        #animation-container element.
+ * @param {DOMElement} target element.
  */
-const sendSpaceKeyEvent = async function(animationInspector, panel) {
-  panel.focus();
-  EventUtils.sendKey("SPACE", panel.ownerGlobal);
+const sendSpaceKeyEvent = async function(animationInspector, element) {
+  element.focus();
+  EventUtils.sendKey("SPACE", element.ownerGlobal);
   await waitForSummaryAndDetail(animationInspector);
 };
 
 /**
  * Set a node class attribute to the given selector.
  *
  * @param {AnimationInspector} animationInspector
  * @param {String} selector
@@ -628,51 +627,45 @@ function assertAnimationsCurrentTime(ani
     animationInspector.state.animations.every(({state}) => state.currentTime === time);
   ok(isTimeEqual, `Current time of animations should be ${ time }`);
 }
 
 /**
  * Check whether the animations are pausing.
  *
  * @param {AnimationInspector} animationInspector
- * @param {DOMElement} panel
- *        #animation-container element.
  */
-function assertAnimationsPausing(animationInspector, panel) {
-  assertAnimationsPausingOrRunning(animationInspector, panel, true);
+function assertAnimationsPausing(animationInspector) {
+  assertAnimationsPausingOrRunning(animationInspector, true);
 }
 
 /**
  * Check whether the animations are pausing/running.
  *
  * @param {AnimationInspector} animationInspector
- * @param {DOMElement} panel
- *        #animation-container element.
  * @param {boolean} shouldPause
  */
-function assertAnimationsPausingOrRunning(animationInspector, panel, shouldPause) {
+function assertAnimationsPausingOrRunning(animationInspector, shouldPause) {
   const hasRunningAnimation =
     animationInspector.state.animations.some(({state}) => state.playState === "running");
 
   if (shouldPause) {
     is(hasRunningAnimation, false, "All animations should be paused");
   } else {
     is(hasRunningAnimation, true, "Animations should be running at least one");
   }
 }
 
 /**
  * Check whether the animations are running.
  *
  * @param {AnimationInspector} animationInspector
- * @param {DOMElement} panel
- *        #animation-container element.
  */
-function assertAnimationsRunning(animationInspector, panel) {
-  assertAnimationsPausingOrRunning(animationInspector, panel, false);
+function assertAnimationsRunning(animationInspector) {
+  assertAnimationsPausingOrRunning(animationInspector, false);
 }
 
 /**
  * Check the <stop> element in the given linearGradientEl for the correct offset
  * and color attributes.
  *
  * @param {Element} linearGradientEl
           <linearGradient> element which has <stop> element.
--- a/devtools/client/jsonview/converter-observer.js
+++ b/devtools/client/jsonview/converter-observer.js
@@ -170,38 +170,34 @@ ConverterObserver.prototype = {
   register: function() {
     const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
     if (!registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
       registrar.registerFactory(JSON_SNIFFER_CLASS_ID,
         JSON_SNIFFER_CLASS_DESCRIPTION,
         JSON_SNIFFER_CONTRACT_ID,
         JsonSnifferFactory);
-      const categoryManager = Cc["@mozilla.org/categorymanager;1"]
-        .getService(Ci.nsICategoryManager);
-      categoryManager.addCategoryEntry(CONTENT_SNIFFER_CATEGORY, JSON_VIEW_TYPE,
+      Services.catMan.addCategoryEntry(CONTENT_SNIFFER_CATEGORY, JSON_VIEW_TYPE,
         JSON_SNIFFER_CONTRACT_ID, false, false);
     }
 
     if (!registrar.isCIDRegistered(JSON_VIEW_CLASS_ID)) {
       registrar.registerFactory(JSON_VIEW_CLASS_ID,
         JSON_VIEW_CLASS_DESCRIPTION,
         JSON_VIEW_CONTRACT_ID,
         JsonViewFactory);
     }
   },
 
   unregister: function() {
     const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
     if (registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
       registrar.unregisterFactory(JSON_SNIFFER_CLASS_ID, JsonSnifferFactory);
-      const categoryManager = Cc["@mozilla.org/categorymanager;1"]
-        .getService(Ci.nsICategoryManager);
-      categoryManager.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
+      Services.catMan.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
         JSON_VIEW_TYPE, false);
     }
 
     if (registrar.isCIDRegistered(JSON_VIEW_CLASS_ID)) {
       registrar.unregisterFactory(JSON_VIEW_CLASS_ID, JsonViewFactory);
     }
   },
 
--- a/devtools/client/themes/common.css
+++ b/devtools/client/themes/common.css
@@ -81,17 +81,17 @@ html|button, html|select {
   max-height: 20rem;
   height: 100%;
   box-sizing: border-box;
 }
 
 .devtools-autocomplete-listbox .autocomplete-item {
   width: 100%;
   background-color: transparent;
-  color: var(--theme-arrowpanel-color);
+  color: var(--theme-popup-color);
   padding: 1px var(--autocomplete-item-padding-inline);
   cursor: default;
   text-overflow: ellipsis;
   white-space: pre;
   overflow: hidden;
 }
 
 .devtools-autocomplete-listbox .autocomplete-item > .initial-value,
@@ -140,23 +140,23 @@ html|button, html|select {
   z-index: -1;
 }
 
 /* Rest of the dark and light theme */
 
 .tooltip-panel.devtools-autocomplete-popup,
 .CodeMirror-hints,
 .CodeMirror-Tern-tooltip {
-  border: 1px solid var(--theme-arrowpanel-border-color);
-  background-color: var(--theme-arrowpanel-background);
-  color: var(--theme-arrowpanel-color);
+  border: 1px solid var(--theme-popup-border-color);
+  background-color: var(--theme-popup-background);
+  color: var(--theme-popup-color);
 }
 
 .devtools-autocomplete-listbox .autocomplete-item:hover {
-  background-color: var(--theme-arrowpanel-dimmed);
+  background-color: var(--theme-popup-dimmed);
 }
 
 .devtools-autocomplete-listbox .autocomplete-selected,
 .devtools-autocomplete-listbox .autocomplete-selected:hover {
   background-color: var(--theme-selection-background);
   color: var(--theme-selection-color);
 }
 
--- a/devtools/client/themes/tooltips.css
+++ b/devtools/client/themes/tooltips.css
@@ -10,23 +10,66 @@
 
 /* Tooltip specific theme variables */
 
 .theme-dark {
   --bezier-diagonal-color: #eee;
   --bezier-grid-color: rgba(0, 0, 0, 0.2);
   --onboarding-link-color: var(--theme-highlight-blue);
   --onboarding-link-active-color: var(--blue-40);
+
+  /* Tooltips */
+  --theme-tooltip-border: #434850;
+  --theme-tooltip-background: rgba(19, 28, 38, .9);
+  --theme-tooltip-shadow: rgba(25, 25, 25, 0.76);
+
+  /* Doorhangers */
+  /* These colors are based on the colors used for doorhangers elsewhere in
+   * Firefox. */
+  --theme-arrowpanel-background: var(--theme-popup-background);
+  --theme-arrowpanel-color: var(--theme-popup-color);
+  --theme-arrowpanel-border-color: var(--theme-popup-border-color);
+  --theme-arrowpanel-separator: rgba(249,249,250,.1);
+  --theme-arrowpanel-dimmed: var(--theme-popup-dimmed);
+  --theme-arrowpanel-dimmed-further: rgba(249,249,250,.15);
+  --theme-arrowpanel-disabled-color: rgba(249,249,250,.5);
 }
 
 .theme-light {
   --bezier-diagonal-color: rgba(0, 0, 0, 0.2);
   --bezier-grid-color: rgba(0, 0, 0, 0.05);
   --onboarding-link-color: var(--blue-60);
   --onboarding-link-active-color: var(--blue-70);
+
+  /* Tooltips */
+  --theme-tooltip-border: #d9e1e8;
+  --theme-tooltip-background: rgba(255, 255, 255, .9);
+  --theme-tooltip-shadow: rgba(155, 155, 155, 0.26);
+
+  /* Doorhangers */
+  /* These colors are based on the colors used for doorhangers elsewhere in
+   * Firefox. */
+  --theme-arrowpanel-background: var(--theme-popup-background);
+  --theme-arrowpanel-color: var(--theme-popup-color);
+  --theme-arrowpanel-border-color: var(--theme-popup-border-color);
+  --theme-arrowpanel-separator: ThreeDShadow;
+  --theme-arrowpanel-dimmed: var(--theme-popup-dimmed);
+  --theme-arrowpanel-dimmed-further: hsla(0,0%,80%,.45);
+  --theme-arrowpanel-disabled-color: GrayText;
+}
+
+:root {
+  --theme-arrowpanel-border-radius: 0px;
+}
+:root[platform="mac"] {
+  --theme-arrowpanel-border-radius: 3.5px;
+}
+
+:root[platform="mac"].theme-light {
+  --theme-arrowpanel-separator: hsla(210,4%,10%,.14);
 }
 
 /* Tooltip: CSS variables tooltip */
 
 .devtools-tooltip-css-variable {
   color: var(--theme-body-color);
   padding: 2px;
 }
@@ -187,23 +230,16 @@
 
 .tooltip-top .tooltip-arrow:before {
   margin-top: -12px;
   transform: rotate(45deg);
 }
 
 /* Tooltip : doorhanger style */
 
-:root {
-  --theme-arrowpanel-border-radius: 0px;
-}
-:root[platform="mac"] {
-  --theme-arrowpanel-border-radius: 3.5px;
-}
-
 .tooltip-container[type="doorhanger"] > .tooltip-panel {
   padding: 2px 0;
   color: var(--theme-arrowpanel-color);
   margin: 4px;
   max-width: 320px;
 }
 
 .tooltip-container[type="doorhanger"] > .tooltip-panel,
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -81,44 +81,33 @@
   --theme-graphs-red: #e57180;
   --theme-graphs-grey: #cccccc;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
   /* Icon filters */
   --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-light);
 
-  /* Tooltips */
-  --theme-tooltip-border: #d9e1e8;
-  --theme-tooltip-background: rgba(255, 255, 255, .9);
-  --theme-tooltip-shadow: rgba(155, 155, 155, 0.26);
-
-  /* Doorhangers */
-  /* These colors are based on the colors used for doorhangers elsewhere in
-   * Firefox. */
-  --theme-arrowpanel-background: -moz-field;
-  --theme-arrowpanel-color: -moz-fieldText;
-  --theme-arrowpanel-border-color: ThreeDShadow;
-  --theme-arrowpanel-separator: ThreeDShadow;
-  --theme-arrowpanel-dimmed: hsla(0,0%,80%,.3);
-  --theme-arrowpanel-dimmed-further: hsla(0,0%,80%,.45);
-  --theme-arrowpanel-disabled-color: GrayText;
+  /* Common popup styles(used by HTMLTooltip and autocomplete) */
+  --theme-popup-background: -moz-field;
+  --theme-popup-color: -moz-fieldText;
+  --theme-popup-border-color: ThreeDShadow;
+  --theme-popup-dimmed: hsla(0,0%,80%,.3);
 
   --theme-messageCloseButtonFilter: invert(0);
 }
 
 /*
  * For doorhangers elsewhere in Firefox, Mac uses fixed colors rather than
  * system colors.
  */
 :root[platform="mac"].theme-light {
-  --theme-arrowpanel-background: hsla(0,0%,99%,.975);
-  --theme-arrowpanel-color: hsl(0,0%,10%);
-  --theme-arrowpanel-border-color: hsla(210,4%,10%,.05);
-  --theme-arrowpanel-separator: hsla(210,4%,10%,.14);
+  --theme-popup-background: hsla(0,0%,99%,.975);
+  --theme-popup-color: hsl(0,0%,10%);
+  --theme-popup-border-color: hsla(210,4%,10%,.05);
 }
 
 :root.theme-dark {
   --theme-body-background: var(--grey-80);
   --theme-sidebar-background: #1B1B1D;
   --theme-contrast-background: #ffb35b;
 
   /* Toolbar */
@@ -183,31 +172,21 @@
   --theme-graphs-red: #eb5368;
   --theme-graphs-grey: #757873;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
   /* Icon filters */
   --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-dark);
 
-  /* Tooltips */
-  --theme-tooltip-border: #434850;
-  --theme-tooltip-background: rgba(19, 28, 38, .9);
-  --theme-tooltip-shadow: rgba(25, 25, 25, 0.76);
-
-  /* Doorhangers */
-  /* These colors are based on the colors used for doorhangers elsewhere in
-   * Firefox. */
-  --theme-arrowpanel-background: var(--grey-60);
-  --theme-arrowpanel-color: rgb(249,249,250);
-  --theme-arrowpanel-border-color: #27272b;
-  --theme-arrowpanel-separator: rgba(249,249,250,.1);
-  --theme-arrowpanel-dimmed: rgba(249,249,250,.1);
-  --theme-arrowpanel-dimmed-further: rgba(249,249,250,.15);
-  --theme-arrowpanel-disabled-color: rgba(249,249,250,.5);
+  /* Common popup styles(used by HTMLTooltip and autocomplete) */
+  --theme-popup-background: var(--grey-60);
+  --theme-popup-color: rgb(249,249,250);
+  --theme-popup-border-color: #27272b;
+  --theme-popup-dimmed: rgba(249,249,250,.1);
 
   --theme-messageCloseButtonFilter: invert(1);
 }
 
 :root {
   --theme-focus-border-color-textbox: #0675d3;
   --theme-textbox-box-shadow: rgba(97,181,255,.75);
 
--- a/devtools/server/actors/errordocs.js
+++ b/devtools/server/actors/errordocs.js
@@ -82,16 +82,18 @@ const ErrorDocs = {
   JSMSG_DEPRECATED_DELETE_OPERAND: "Delete_in_strict_mode",
   JSMSG_MISSING_FORMAL: "Missing_formal_parameter",
   JSMSG_CANT_TRUNCATE_ARRAY: "Non_configurable_array_element",
   JSMSG_INCOMPATIBLE_PROTO: "Called_on_incompatible_type",
   JSMSG_INCOMPATIBLE_METHOD: "Called_on_incompatible_type",
   JSMSG_BAD_INSTANCEOF_RHS: "invalid_right_hand_side_instanceof_operand",
   JSMSG_EMPTY_ARRAY_REDUCE: "Reduce_of_empty_array_with_no_initial_value",
   JSMSG_NOT_ITERABLE: "is_not_iterable",
+  JSMSG_PROPERTY_FAIL: "cant_access_property",
+  JSMSG_PROPERTY_FAIL_EXPR: "cant_access_property",
 };
 
 const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Mixed_content";
 const TRACKING_PROTECTION_LEARN_MORE = "https://developer.mozilla.org/Firefox/Privacy/Tracking_Protection";
 const INSECURE_PASSWORDS_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Insecure_passwords";
 const PUBLIC_KEY_PINS_LEARN_MORE = "https://developer.mozilla.org/docs/Web/HTTP/Public_Key_Pinning";
 const STRICT_TRANSPORT_SECURITY_LEARN_MORE = "https://developer.mozilla.org/docs/Web/HTTP/Headers/Strict-Transport-Security";
 const WEAK_SIGNATURE_ALGORITHM_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Weak_Signature_Algorithm";
--- a/devtools/server/actors/network-monitor/channel-event-sink.js
+++ b/devtools/server/actors/network-monitor/channel-event-sink.js
@@ -2,16 +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 {Cc, Ci, Cm, Cr, components} = require("chrome");
 const ChromeUtils = require("ChromeUtils");
 const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
+const Services = require("Services");
 
 /**
  * This is a nsIChannelEventSink implementation that monitors channel redirects and
  * informs the registered StackTraceCollector about the old and new channels.
  */
 const SINK_CLASS_DESCRIPTION = "NetworkMonitor Channel Event Sink";
 const SINK_CLASS_ID = components.ID("{e89fa076-c845-48a8-8c45-2604729eba1d}");
 const SINK_CONTRACT_ID = "@mozilla.org/network/monitor/channeleventsink;1";
@@ -58,25 +59,25 @@ ChannelEventSinkFactory.register = funct
     return;
   }
 
   registrar.registerFactory(SINK_CLASS_ID,
                             SINK_CLASS_DESCRIPTION,
                             SINK_CONTRACT_ID,
                             ChannelEventSinkFactory);
 
-  XPCOMUtils.categoryManager.addCategoryEntry(SINK_CATEGORY_NAME, SINK_CONTRACT_ID,
+  Services.catMan.addCategoryEntry(SINK_CATEGORY_NAME, SINK_CONTRACT_ID,
     SINK_CONTRACT_ID, false, true);
 };
 
 ChannelEventSinkFactory.unregister = function() {
   const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
   registrar.unregisterFactory(SINK_CLASS_ID, ChannelEventSinkFactory);
 
-  XPCOMUtils.categoryManager.deleteCategoryEntry(SINK_CATEGORY_NAME, SINK_CONTRACT_ID,
+  Services.catMan.deleteCategoryEntry(SINK_CATEGORY_NAME, SINK_CONTRACT_ID,
     false);
 };
 
 ChannelEventSinkFactory.getService = function() {
   // Make sure the ChannelEventSink service is registered before accessing it
   ChannelEventSinkFactory.register();
 
   return Cc[SINK_CONTRACT_ID].getService(Ci.nsIChannelEventSink).wrappedJSObject;
--- a/devtools/shared/heapsnapshot/DeserializedNode.cpp
+++ b/devtools/shared/heapsnapshot/DeserializedNode.cpp
@@ -82,18 +82,17 @@ class DeserializedEdgeRange : public Edg
   void settle() {
     if (i >= node->edges.length()) {
       front_ = nullptr;
       return;
     }
 
     auto& edge = node->edges[i];
     auto referent = node->getEdgeReferent(edge);
-    currentEdge = Edge(edge.name
-                ? NS_strdup(edge.name) : nullptr, referent);
+    currentEdge = Edge(edge.name ? NS_xstrdup(edge.name) : nullptr, referent);
     front_ = &currentEdge;
   }
 
 public:
   explicit DeserializedEdgeRange(DeserializedNode& node)
     : node(&node)
     , i(0)
   {
--- a/devtools/shared/heapsnapshot/HeapSnapshot.cpp
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.cpp
@@ -142,18 +142,18 @@ struct GetOrInternStringMatcher
 
   explicit GetOrInternStringMatcher(InternedStringSet& strings) : internedStrings(strings) { }
 
   const CharT* match(const std::string* str) {
     MOZ_ASSERT(str);
     size_t length = str->length() / sizeof(CharT);
     auto tempString = reinterpret_cast<const CharT*>(str->data());
 
-    UniqueFreePtr<CharT[]> owned(NS_strndup(tempString, length));
-    if (!owned || !internedStrings.append(std::move(owned)))
+    UniqueFreePtr<CharT[]> owned(NS_xstrndup(tempString, length));
+    if (!internedStrings.append(std::move(owned)))
       return nullptr;
 
     return internedStrings.back().get();
   }
 
   const CharT* match(uint64_t ref) {
     if (MOZ_LIKELY(ref < internedStrings.length())) {
       auto& string = internedStrings[ref];
--- a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
+++ b/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
@@ -182,18 +182,17 @@ public:
 const char16_t Concrete<FakeNode>::concreteTypeName[] = u"FakeNode";
 
 } // namespace ubi
 } // namespace JS
 
 void AddEdge(FakeNode& node, FakeNode& referent, const char16_t* edgeName = nullptr) {
   char16_t* ownedEdgeName = nullptr;
   if (edgeName) {
-    ownedEdgeName = NS_strdup(edgeName);
-    ASSERT_NE(ownedEdgeName, nullptr);
+    ownedEdgeName = NS_xstrdup(edgeName);
   }
 
   JS::ubi::Edge edge(ownedEdgeName, &referent);
   ASSERT_TRUE(node.edges.append(std::move(edge)));
 }
 
 
 // Custom GMock Matchers
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -14309,20 +14309,16 @@ nsDocShell::GetColorMatrix(uint32_t* aMa
   NS_ENSURE_ARG_POINTER(aMatrixLen);
   *aMatrixLen = 0;
 
   NS_ENSURE_ARG_POINTER(aMatrix);
   *aMatrix = nullptr;
 
   if (mColorMatrix) {
     *aMatrix = (float*)moz_xmalloc(20 * sizeof(float));
-    if (!*aMatrix) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
     MOZ_ASSERT(20 * sizeof(float) == sizeof(mColorMatrix->components));
     *aMatrixLen = 20;
     memcpy(*aMatrix, mColorMatrix->components, 20 * sizeof(float));
   }
 
   return NS_OK;
 }
 
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -182,21 +182,18 @@ interface nsIWebNavigation : nsISupports
   /**
    * Force relevant cookies to be sent with this load even if normally they
    * wouldn't be.
    */
   const unsigned long LOAD_FLAGS_FORCE_ALLOW_COOKIES = 0x20000;
 
   /**
    * Prevent the owner principal from being inherited for this load.
-   * Note: Within Gecko we use the term principal rather than owners
-   *       but some legacy addons might still rely on the outdated term.
    */
   const unsigned long LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL = 0x40000;
-  const unsigned long LOAD_FLAGS_DISALLOW_INHERIT_OWNER     = 0x40000;
 
   /**
    * Overwrite the returned error code with a specific result code
    * when an error page is displayed.
    */
   const unsigned long LOAD_FLAGS_ERROR_LOAD_CHANGES_RV = 0x80000;
 
   /**
--- a/docshell/shistory/nsISHistory.idl
+++ b/docshell/shistory/nsISHistory.idl
@@ -72,24 +72,16 @@ interface nsISHistory: nsISupports
    * @return                  <code>NS_OK</code> history entry for 
    *                          the index is obtained successfully.
    *                          <code>NS_ERROR_FAILURE</code> Error in obtaining
    *                          history entry for the given index.
    */
    nsISHEntry getEntryAtIndex(in long index, in boolean modifyIndex);
 
   /**
-   * Load the entry at given index to root docshell directly in order to
-   * restore to an entry in grouped session history navigation or session
-   * restore case. This function will not notify nsISHistoryListener, as it's
-   * not considered a normal history navigation.
-   */
-   void restoreToEntryAtIndex(in long index);
-
-  /**
    * Called to purge older documents from history.
    * Documents can be removed from session history for various 
    * reasons. For example to  control memory usage of the browser, to 
    * prevent users from loading documents from history, to erase evidence of
    * prior page loads etc...
    *
    * @param numEntries        The number of toplevel documents to be
    *                          purged from history. During purge operation,
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -645,18 +645,17 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntr
 
   if (!currentPersist) {
     NOTIFY_LISTENERS(OnHistoryReplaceEntry, (currentIndex));
     NS_ENSURE_SUCCESS(currentTxn->SetSHEntry(aSHEntry), NS_ERROR_FAILURE);
     currentTxn->SetPersist(aPersist);
     return NS_OK;
   }
 
-  nsCOMPtr<nsISHTransaction> txn(new nsSHTransaction());
-
+  nsCOMPtr<nsISHTransaction> txn = new nsSHTransaction();
   nsCOMPtr<nsIURI> uri;
   aSHEntry->GetURI(getter_AddRefs(uri));
   NOTIFY_LISTENERS(OnHistoryNewEntry, (uri, currentIndex));
 
   // If a listener has changed mIndex, we need to get currentTxn again,
   // otherwise we'll be left at an inconsistent state (see bug 320742)
   if (currentIndex != mIndex) {
     GetTransactionAtIndex(mIndex, getter_AddRefs(currentTxn));
@@ -1177,32 +1176,16 @@ nsSHistory::ReloadCurrentEntry()
                               (mIndex, currentURI, &canNavigate));
   if (!canNavigate) {
     return NS_OK;
   }
 
   return LoadEntry(mIndex, LOAD_HISTORY, HIST_CMD_RELOAD);
 }
 
-NS_IMETHODIMP
-nsSHistory::RestoreToEntryAtIndex(int32_t aIndex)
-{
-  mRequestedIndex = aIndex;
-
-  nsCOMPtr<nsISHEntry> nextEntry;
-  GetEntryAtIndex(mRequestedIndex, false, getter_AddRefs(nextEntry));
-  if (!nextEntry) {
-    mRequestedIndex = -1;
-    return NS_ERROR_FAILURE;
-  }
-
-  // XXX We may want to ensure docshell is currently holding about:blank
-  return InitiateLoad(nextEntry, mRootDocShell, LOAD_HISTORY);
-}
-
 void
 nsSHistory::EvictOutOfRangeWindowContentViewers(int32_t aIndex)
 {
   // XXX rename method to EvictContentViewersExceptAroundIndex, or something.
 
   // We need to release all content viewers that are no longer in the range
   //
   //  aIndex - VIEWER_WINDOW to aIndex + VIEWER_WINDOW
--- a/dom/base/BodyUtil.cpp
+++ b/dom/base/BodyUtil.cpp
@@ -253,20 +253,16 @@ private:
       ErrorResult rv;
       mFormData->Append(name, NS_ConvertUTF8toUTF16(body), rv);
       MOZ_ASSERT(!rv.Failed());
     } else {
       // Unfortunately we've to copy the data first since all our strings are
       // going to free it. We also need fallible alloc, so we can't just use
       // ToNewCString().
       char* copy = static_cast<char*>(moz_xmalloc(body.Length()));
-      if (!copy) {
-        NS_WARNING("Failed to copy File entry body.");
-        return false;
-      }
       nsCString::const_iterator bodyIter, bodyEnd;
       body.BeginReading(bodyIter);
       body.EndReading(bodyEnd);
       char *p = copy;
       while (bodyIter != bodyEnd) {
         *p++ = *bodyIter++;
       }
       p = nullptr;
--- a/dom/base/NodeUbiReporting.cpp
+++ b/dom/base/NodeUbiReporting.cpp
@@ -30,26 +30,26 @@ JS::ubi::Concrete<nsINode>::edges(JSCont
   AutoSuppressGCAnalysis suppress;
   auto range = js::MakeUnique<SimpleEdgeRange>();
   if (!range) {
     return nullptr;
   }
   if (get().GetParent()) {
     char16_t* edgeName = nullptr;
     if (wantNames) {
-      edgeName = NS_strdup(u"Parent Node");
+      edgeName = NS_xstrdup(u"Parent Node");
     }
     if (!range->addEdge(JS::ubi::Edge(edgeName, get().GetParent()))) {
       return nullptr;
     }
   }
   for (auto curr = get().GetFirstChild(); curr; curr = curr->GetNextSibling()) {
     char16_t* edgeName = nullptr;
     if (wantNames) {
-      edgeName = NS_strdup(u"Child Node");
+      edgeName = NS_xstrdup(u"Child Node");
     }
     if (!range->addEdge(JS::ubi::Edge(edgeName, curr))) {
       return nullptr;
     }
   }
   return js::UniquePtr<EdgeRange>(range.release());
 }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2121,18 +2121,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetClassName(JS::Handle<JS::Value> aObject, JSContext* aCx,
                                char** aName)
 {
   // Our argument must be a non-null object.
   if (aObject.isPrimitive()) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
-  *aName = NS_strdup(JS_GetClass(aObject.toObjectOrNull())->name);
-  MOZ_ASSERT(*aName, "NS_strdup should be infallible.");
+  *aName = NS_xstrdup(JS_GetClass(aObject.toObjectOrNull())->name);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetVisitedDependentComputedStyle(
                     Element *aElement, const nsAString& aPseudoElement,
                     const nsAString& aPropertyName, nsAString& aResult)
 {
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -24,17 +24,19 @@
 #include "nsIInputStream.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIMemoryReporter.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
 #include "xpcpublic.h"
+#include "js/CompilationAndEvaluation.h"
 #include "js/JSON.h"
+#include "js/SourceBufferHolder.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/ChildProcessMessageManager.h"
 #include "mozilla/dom/ChromeMessageBroadcaster.h"
 #include "mozilla/dom/File.h"
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -9,16 +9,19 @@
  * invoked from the JavaScript code generated from IDL interfaces.
  * The goal of the utility functions is to cut down on the size of
  * the generated code itself.
  */
 
 #include "nsJSUtils.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/OffThreadScriptCompilation.h"
+#include "js/SourceBufferHolder.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptElement.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.h"
--- a/dom/crypto/CryptoBuffer.cpp
+++ b/dom/crypto/CryptoBuffer.cpp
@@ -170,19 +170,16 @@ CryptoBuffer::ToArrayBuffer(JSContext* a
 bool
 CryptoBuffer::ToNewUnsignedBuffer(uint8_t** aBuf, uint32_t* aBufLen) const
 {
   MOZ_ASSERT(aBuf);
   MOZ_ASSERT(aBufLen);
 
   uint32_t dataLen = Length();
   uint8_t* tmp = reinterpret_cast<uint8_t*>(moz_xmalloc(dataLen));
-  if (NS_WARN_IF(!tmp)) {
-    return false;
-  }
 
   memcpy(tmp, Elements(), dataLen);
   *aBuf = tmp;
   *aBufLen = dataLen;
   return true;
 }
 
 // "BigInt" comes from the WebCrypto spec
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -263,19 +263,17 @@ EventListenerService::GetEventTargetChai
                                           nullptr, nullptr, nullptr, &targets);
   NS_ENSURE_SUCCESS(rv, rv);
   int32_t count = targets.Length();
   if (count == 0) {
     return NS_OK;
   }
 
   *aOutArray =
-    static_cast<EventTarget**>(
-      moz_xmalloc(sizeof(EventTarget*) * count));
-  NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY);
+    static_cast<EventTarget**>(moz_xmalloc(sizeof(EventTarget*) * count));
 
   for (int32_t i = 0; i < count; ++i) {
     NS_ADDREF((*aOutArray)[i] = targets[i]);
   }
   *aCount = count;
 
   return NS_OK;
 }
--- a/dom/file/uri/BlobURL.cpp
+++ b/dom/file/uri/BlobURL.cpp
@@ -217,17 +217,16 @@ BlobURL::GetClassDescription(nsACString&
 }
 
 NS_IMETHODIMP
 BlobURL::GetClassID(nsCID * *aClassID)
 {
   // Make sure to modify any subclasses as needed if this ever
   // changes to not call the virtual GetClassIDNoAlloc.
   *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
-  NS_ENSURE_TRUE(*aClassID, NS_ERROR_OUT_OF_MEMORY);
 
   return GetClassIDNoAlloc(*aClassID);
 }
 
 NS_IMETHODIMP
 BlobURL::GetFlags(uint32_t *aFlags)
 {
   *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -4024,19 +4024,16 @@ GetStringValueFromBundlePlist(const nsAS
   if (valueCString) {
     aValue.Assign(valueCString);
     return NS_OK;
   }
 
   CFIndex maxLength =
     CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
   char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
-  if (!valueBuffer) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
 
   if (!CFStringGetCString(value, valueBuffer, maxLength,
                           kCFStringEncodingUTF8)) {
     free(valueBuffer);
     return NS_ERROR_FAILURE;
   }
 
   aValue.Assign(valueBuffer);
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1160,18 +1160,16 @@ nsPluginHost::GetPluginTags(uint32_t* aP
   RefPtr<nsPluginTag> plugin = mPlugins;
   while (plugin != nullptr) {
     count++;
     plugin = plugin->mNext;
   }
 
   *aResults = static_cast<nsIPluginTag**>
                          (moz_xmalloc((fakeCount + count) * sizeof(**aResults)));
-  if (!*aResults)
-    return NS_ERROR_OUT_OF_MEMORY;
 
   *aPluginCount = count + fakeCount;
 
   plugin = mPlugins;
   for (uint32_t i = 0; i < count; i++) {
     (*aResults)[i] = plugin;
     NS_ADDREF((*aResults)[i]);
     plugin = plugin->mNext;
@@ -3638,18 +3636,17 @@ nsPluginHost::ParsePostBufferToFixHeader
     // of ContentLenHeader value in this case.
 
     newBufferLen = dataLen + headersLen;
     // in case there were single LFs in headers
     // reserve an extra space for CR will be added before each single LF
     int cntSingleLF = singleLF.Length();
     newBufferLen += cntSingleLF;
 
-    if (!(*outPostData = p = (char*)moz_xmalloc(newBufferLen)))
-      return NS_ERROR_OUT_OF_MEMORY;
+    *outPostData = p = (char*)moz_xmalloc(newBufferLen);
 
     // deal with single LF
     const char *s = inPostData;
     if (cntSingleLF) {
       for (int i=0; i<cntSingleLF; i++) {
         const char *plf = singleLF.ElementAt(i); // ptr to single LF in headers
         int n = plf - s; // bytes to copy
         if (n) { // for '\n\n' there is nothing to memcpy
@@ -3667,18 +3664,17 @@ nsPluginHost::ParsePostBufferToFixHeader
       memcpy(p, s, headersLen); // copy the rest
       p += headersLen;
     }
   } else  if (dataLen) { // no ContentLenHeader is found but there is a data
     // make new output buffer big enough
     // to keep ContentLenHeader+value followed by data
     uint32_t l = sizeof(ContentLenHeader) + sizeof(CRLFCRLF) + 32;
     newBufferLen = dataLen + l;
-    if (!(*outPostData = p = (char*)moz_xmalloc(newBufferLen)))
-      return NS_ERROR_OUT_OF_MEMORY;
+    *outPostData = p = (char*)moz_xmalloc(newBufferLen);
     headersLen = snprintf(p, l,"%s: %u%s", ContentLenHeader, dataLen, CRLFCRLF);
     if (headersLen == l) { // if snprintf has ate all extra space consider this as an error
       free(p);
       *outPostData = 0;
       return NS_ERROR_FAILURE;
     }
     p += headersLen;
     newBufferLen = headersLen + dataLen;
--- a/dom/plugins/base/nsPluginsDirDarwin.cpp
+++ b/dom/plugins/base/nsPluginsDirDarwin.cpp
@@ -202,35 +202,25 @@ static void ParsePlistPluginInfo(nsPlugi
   }
 
   AutoCFTypeObject mimeDictAutorelease(mimeDict);
   int mimeDictKeyCount = ::CFDictionaryGetCount(mimeDict);
 
   // Allocate memory for mime data
   int mimeDataArraySize = mimeDictKeyCount * sizeof(char*);
   info.fMimeTypeArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
-  if (!info.fMimeTypeArray)
-    return;
   memset(info.fMimeTypeArray, 0, mimeDataArraySize);
   info.fExtensionArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
-  if (!info.fExtensionArray)
-    return;
   memset(info.fExtensionArray, 0, mimeDataArraySize);
   info.fMimeDescriptionArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
-  if (!info.fMimeDescriptionArray)
-    return;
   memset(info.fMimeDescriptionArray, 0, mimeDataArraySize);
 
   // Allocate memory for mime dictionary keys and values
   mozilla::UniquePtr<CFTypeRef[]> keys(new CFTypeRef[mimeDictKeyCount]);
-  if (!keys)
-    return;
   mozilla::UniquePtr<CFTypeRef[]> values(new CFTypeRef[mimeDictKeyCount]);
-  if (!values)
-    return;
 
   info.fVariantCount = 0;
 
   ::CFDictionaryGetKeysAndValues(mimeDict, keys.get(), values.get());
   for (int i = 0; i < mimeDictKeyCount; i++) {
     CFTypeRef mimeString = keys[i];
     if (!mimeString || ::CFGetTypeID(mimeString) != ::CFStringGetTypeID()) {
       continue;
@@ -329,20 +319,18 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
 #endif
   return NS_OK;
 }
 
 static char* p2cstrdup(StringPtr pstr)
 {
   int len = pstr[0];
   char* cstr = static_cast<char*>(moz_xmalloc(len + 1));
-  if (cstr) {
-    memmove(cstr, pstr + 1, len);
-    cstr[len] = '\0';
-  }
+  memmove(cstr, pstr + 1, len);
+  cstr[len] = '\0';
   return cstr;
 }
 
 static char* GetNextPluginStringFromHandle(Handle h, short *index)
 {
   char *ret = p2cstrdup((unsigned char*)(*h + *index));
   *index += (ret ? strlen(ret) : 0) + 1;
   return ret;
@@ -442,25 +430,19 @@ nsresult nsPluginFile::GetPluginInfo(nsP
       if (mi.infoStrings)  // it's possible some plugins have infoStrings missing
         ::HLock(mi.infoStrings);
     }
   }
 
   // Fill in the info struct based on the data in the BPSupportedMIMETypes struct
   int variantCount = info.fVariantCount;
   info.fMimeTypeArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
-  if (!info.fMimeTypeArray)
-    return NS_ERROR_OUT_OF_MEMORY;
   info.fExtensionArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
-  if (!info.fExtensionArray)
-    return NS_ERROR_OUT_OF_MEMORY;
   if (mi.infoStrings) {
     info.fMimeDescriptionArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
-    if (!info.fMimeDescriptionArray)
-      return NS_ERROR_OUT_OF_MEMORY;
   }
   short mimeIndex = 2;
   short descriptionIndex = 2;
   for (int i = 0; i < variantCount; i++) {
     info.fMimeTypeArray[i] = GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
     info.fExtensionArray[i] = GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
     if (mi.infoStrings)
       info.fMimeDescriptionArray[i] = GetNextPluginStringFromHandle(mi.infoStrings, &descriptionIndex);
--- a/dom/push/PushNotifier.cpp
+++ b/dom/push/PushNotifier.cpp
@@ -219,19 +219,16 @@ PushData::Binary(uint32_t* aDataLen, uin
 
   *aData = nullptr;
   if (mData.IsEmpty()) {
     *aDataLen = 0;
     return NS_OK;
   }
   uint32_t length = mData.Length();
   uint8_t* data = static_cast<uint8_t*>(moz_xmalloc(length * sizeof(uint8_t)));
-  if (!data) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
   memcpy(data, mData.Elements(), length * sizeof(uint8_t));
   *aDataLen = length;
   *aData = data;
   return NS_OK;
 }
 
 PushMessage::PushMessage(nsIPrincipal* aPrincipal, nsIPushData* aData)
   : mPrincipal(aPrincipal)
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -9,16 +9,19 @@
 #include "ScriptLoadRequest.h"
 #include "ScriptTrace.h"
 #include "ModuleLoadRequest.h"
 #include "ModuleScript.h"
 
 #include "prsystem.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/OffThreadScriptCompilation.h"
+#include "js/SourceBufferHolder.h"
 #include "js/Utility.h"
 #include "xpcpublic.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContent.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
--- a/dom/simpledb/ActorsParent.cpp
+++ b/dom/simpledb/ActorsParent.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/dom/quota/FileStreams.h"
 #include "mozilla/dom/quota/MemoryOutputStream.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsIFileStreams.h"
-#include "nsISimpleEnumerator.h"
+#include "nsIDirectoryEnumerator.h"
 #include "nsStringStream.h"
 #include "prio.h"
 #include "SimpleDBCommon.h"
 
 #define DISABLE_ASSERTS_FOR_FUZZING 0
 
 #if DISABLE_ASSERTS_FOR_FUZZING
 #define ASSERT_UNLESS_FUZZING(...) do { } while (0)
@@ -1904,17 +1904,17 @@ QuotaClient::GetUsageForOrigin(Persisten
   rv = directory->Append(NS_LITERAL_STRING(SDB_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   DebugOnly<bool> exists;
   MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool hasMore;
   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
          hasMore && !aCanceled) {
--- a/dom/simpledb/SDBResults.cpp
+++ b/dom/simpledb/SDBResults.cpp
@@ -29,19 +29,16 @@ SDBResult::GetAsArray(uint32_t* aDataLen
     *aDataLen = 0;
     *aData = nullptr;
     return NS_OK;
   }
 
   uint32_t length = mData.Length();
 
   uint8_t* data = static_cast<uint8_t*>(moz_xmalloc(length * sizeof(uint8_t)));
-  if (!data) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
 
   memcpy(data, mData.BeginReading(), length * sizeof(uint8_t));
 
   *aDataLen = length;
   *aData = data;
   return NS_OK;
 }
 
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -20,16 +20,18 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIStreamLoader.h"
 #include "nsIStreamListenerTee.h"
 #include "nsIThreadRetargetableRequest.h"
 #include "nsIURI.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceBufferHolder.h"
 #include "nsError.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsDocShellCID.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetUtil.h"
 #include "nsIPipe.h"
 #include "nsIOutputStream.h"
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1,18 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WorkerPrivate.h"
 
+#include "js/CompilationAndEvaluation.h"
 #include "js/LocaleSensitive.h"
 #include "js/MemoryMetrics.h"
+#include "js/SourceBufferHolder.h"
 #include "MessageEventRunnable.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientSource.h"
 #include "mozilla/dom/ClientState.h"
 #include "mozilla/dom/Console.h"
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -14,16 +14,18 @@
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/RegisterWorkletBindings.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ScriptLoader.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceBufferHolder.h"
 #include "nsIInputStreamPump.h"
 #include "nsIThreadRetargetableRequest.h"
 #include "nsNetUtil.h"
 #include "xpcprivate.h"
 
 namespace mozilla {
 namespace dom {
 
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -29,17 +29,17 @@ using namespace mozilla::dom;
 
 nsXBLProtoImplField::nsXBLProtoImplField(const char16_t* aName, const char16_t* aReadOnly)
   : mNext(nullptr),
     mFieldText(nullptr),
     mFieldTextLength(0),
     mLineNumber(0)
 {
   MOZ_COUNT_CTOR(nsXBLProtoImplField);
-  mName = NS_strdup(aName);  // XXXbz make more sense to use a stringbuffer?
+  mName = NS_xstrdup(aName);  // XXXbz make more sense to use a stringbuffer?
 
   mJSAttributes = JSPROP_ENUMERATE;
   if (aReadOnly) {
     nsAutoString readOnly; readOnly.Assign(aReadOnly);
     if (readOnly.LowerCaseEqualsLiteral("true"))
       mJSAttributes |= JSPROP_READONLY;
   }
 }
--- a/dom/xslt/xpath/txNodeSet.cpp
+++ b/dom/xslt/xpath/txNodeSet.cpp
@@ -520,22 +520,18 @@ bool txNodeSet::ensureGrowSize(int32_t a
     // This isn't 100% safe. But until someone manages to make a 1gig nodeset
     // it should be ok.
     int32_t newLength = std::max(oldLength, kTxNodeSetMinSize);
 
     while (newLength < ensureSize) {
         newLength *= kTxNodeSetGrowFactor;
     }
 
-    txXPathNode* newArr = static_cast<txXPathNode*>
-                                     (moz_xmalloc(newLength *
-                                                         sizeof(txXPathNode)));
-    if (!newArr) {
-        return false;
-    }
+    txXPathNode* newArr =
+      static_cast<txXPathNode*>(moz_xmalloc(newLength * sizeof(txXPathNode)));
 
     txXPathNode* dest = newArr;
     if (mDirection == kReversed) {
         dest += newLength - oldSize;
     }
 
     if (oldSize > 0) {
         LOG_CHUNK_MOVE(mStart, dest, oldSize);
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -1469,21 +1469,16 @@ txVariable::Convert(nsIVariant *aValue, 
 
             NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE ||
                          type == nsIDataType::VTYPE_INTERFACE_IS,
                          "Huh, we checked this in SetParameter?");
 
             nsISupports** values = static_cast<nsISupports**>(array);
 
             RefPtr<txNodeSet> nodeSet = new txNodeSet(nullptr);
-            if (!nodeSet) {
-                NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, values);
-
-                return NS_ERROR_OUT_OF_MEMORY;
-            }
 
             uint32_t i;
             for (i = 0; i < count; ++i) {
                 nsISupports *supports = values[i];
                 nsCOMPtr<nsINode> node = do_QueryInterface(supports);
                 NS_ASSERTION(node, "Huh, we checked this in SetParameter?");
 
                 nsAutoPtr<txXPathNode> xpathNode(
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -81,16 +81,18 @@
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/XULDocumentBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceBufferHolder.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
 #include "mozAutoDocUpdate.h"
 #include "xpcpublic.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "nsIConsoleService.h"
 
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -13,16 +13,18 @@
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDocument.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/DeclarationBlock.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceBufferHolder.h"
 #include "nsFocusManager.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsNameSpaceManager.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptContext.h"
--- a/editor/spellchecker/EditorSpellCheck.cpp
+++ b/editor/spellchecker/EditorSpellCheck.cpp
@@ -580,29 +580,25 @@ EditorSpellCheck::GetDictionaryList(char
   char16_t **tmpPtr = 0;
 
   if (dictList.IsEmpty()) {
     // If there are no dictionaries, return an array containing
     // one element and a count of one.
 
     tmpPtr = (char16_t **)moz_xmalloc(sizeof(char16_t *));
 
-    NS_ENSURE_TRUE(tmpPtr, NS_ERROR_OUT_OF_MEMORY);
-
     *tmpPtr          = 0;
     *aDictionaryList = tmpPtr;
     *aCount          = 0;
 
     return NS_OK;
   }
 
   tmpPtr = (char16_t **)moz_xmalloc(sizeof(char16_t *) * dictList.Length());
 
-  NS_ENSURE_TRUE(tmpPtr, NS_ERROR_OUT_OF_MEMORY);
-
   *aDictionaryList = tmpPtr;
   *aCount          = dictList.Length();
 
   for (uint32_t i = 0; i < *aCount; i++) {
     tmpPtr[i] = ToNewUnicode(dictList[i]);
   }
 
   return rv;
--- a/extensions/auth/nsAuthGSSAPI.cpp
+++ b/extensions/auth/nsAuthGSSAPI.cpp
@@ -511,17 +511,17 @@ nsAuthGSSAPI::GetNextToken(const void *i
         // The important thing is that we do NOT reset the
         // context here because it will be needed on the
         // next call.
         //
     }
 
     *outTokenLen = output_token.length;
     if (output_token.length != 0)
-        *outToken = nsMemory::Clone(output_token.value, output_token.length);
+        *outToken = moz_xmemdup(output_token.value, output_token.length);
     else
         *outToken = nullptr;
 
     gss_release_buffer_ptr(&minor_status, &output_token);
 
     if (major_status == GSS_S_COMPLETE)
         rv = NS_SUCCESS_AUTH_FINISHED;
     else
@@ -560,17 +560,17 @@ nsAuthGSSAPI::Unwrap(const void *inToken
         Reset();
         gss_release_buffer_ptr(&minor_status, &output_token);
         return NS_ERROR_FAILURE;
     }
 
     *outTokenLen = output_token.length;
 
     if (output_token.length)
-        *outToken = nsMemory::Clone(output_token.value, output_token.length);
+        *outToken = moz_xmemdup(output_token.value, output_token.length);
     else
         *outToken = nullptr;
 
     gss_release_buffer_ptr(&minor_status, &output_token);
 
     return NS_OK;
 }
 
@@ -602,14 +602,14 @@ nsAuthGSSAPI::Wrap(const void *inToken,
         Reset();
         gss_release_buffer_ptr(&minor_status, &output_token);
         return NS_ERROR_FAILURE;
     }
 
     *outTokenLen = output_token.length;
 
     /* it is not possible for output_token.length to be zero */
-    *outToken = nsMemory::Clone(output_token.value, output_token.length);
+    *outToken = moz_xmemdup(output_token.value, output_token.length);
     gss_release_buffer_ptr(&minor_status, &output_token);
 
     return NS_OK;
 }
 
--- a/extensions/auth/nsAuthSASL.cpp
+++ b/extensions/auth/nsAuthSASL.cpp
@@ -100,20 +100,16 @@ nsAuthSASL::GetNextToken(const void *inT
         // If we were doing security layers then we'd care what the
         // server had sent us. We're not, so all we had to do was make
         // sure that the signature was correct with the above unwrap()
         free(unwrappedToken);
 
         NS_CopyUnicodeToNative(mUsername, userbuf);
         messageLen = userbuf.Length() + 4 + 1;
         message = (char *)moz_xmalloc(messageLen);
-        if (!message) {
-          Reset();
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
         message[0] = 0x01; // No security layer
         message[1] = 0x00;
         message[2] = 0x00;
         message[3] = 0x00; // Maxbuf must be zero if we've got no sec layer
         strcpy(message+4, userbuf.get());
         // Userbuf should not be nullptr terminated, so trim the trailing nullptr
         // when wrapping the message
         rv = mInnerModule->Wrap((void *) message, messageLen-1, false,
--- a/extensions/auth/nsAuthSSPI.cpp
+++ b/extensions/auth/nsAuthSSPI.cpp
@@ -336,18 +336,16 @@ nsAuthSSPI::GetNextToken(const void *inT
 
     if (inToken) {
         if (mIsFirst) {
             // First time if it comes with a token,
             // the token represents the server certificate.
             mIsFirst = false;
             mCertDERLength = inTokenLen;
             mCertDERData = moz_xmalloc(inTokenLen);
-            if (!mCertDERData)
-                return NS_ERROR_OUT_OF_MEMORY;
             memcpy(mCertDERData, inToken, inTokenLen);
 
             // We are starting a new authentication sequence.
             // If we have already initialized our
             // security context, then we're in trouble because it means that the
             // first sequence failed.  We need to bail or else we might end up in
             // an infinite loop.
             if (mCtxt.dwLower || mCtxt.dwUpper) {
@@ -380,19 +378,16 @@ nsAuthSSPI::GetNextToken(const void *inT
 
                 // Then add it to the array of sec buffers accordingly.
                 ib[ibd.cBuffers].BufferType = SECBUFFER_CHANNEL_BINDINGS;
                 ib[ibd.cBuffers].cbBuffer =
                         pendpoint_binding.cbApplicationDataLength
                         + pendpoint_binding.dwApplicationDataOffset;
 
                 sspi_cbt = (char *) moz_xmalloc(ib[ibd.cBuffers].cbBuffer);
-                if (!sspi_cbt){
-                    return NS_ERROR_OUT_OF_MEMORY;
-                }
 
                 // Helper to write in the memory block that stores the CBT
                 char* sspi_cbt_ptr = sspi_cbt;
 
                 ib[ibd.cBuffers].pvBuffer = sspi_cbt;
                 ibd.cBuffers++;
 
                 memcpy(sspi_cbt_ptr, &pendpoint_binding,
@@ -455,21 +450,16 @@ nsAuthSSPI::GetNextToken(const void *inT
     }
 
     obd.ulVersion = SECBUFFER_VERSION;
     obd.cBuffers = 1;
     obd.pBuffers = &ob;
     ob.BufferType = SECBUFFER_TOKEN;
     ob.cbBuffer = mMaxTokenLen;
     ob.pvBuffer = moz_xmalloc(ob.cbBuffer);
-    if (!ob.pvBuffer){
-        if (sspi_cbt)
-            free(sspi_cbt);
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
     memset(ob.pvBuffer, 0, ob.cbBuffer);
 
     NS_ConvertUTF8toUTF16 wSN(mServiceName);
     SEC_WCHAR *sn = (SEC_WCHAR *) wSN.get();
 
     rc = (sspi->InitializeSecurityContextW)(&mCred,
                                             ctxIn,
                                             sn,
@@ -524,18 +514,16 @@ nsAuthSSPI::Unwrap(const void *inToken,
     ibd.cBuffers = 2;
     ibd.pBuffers = ib;
     ibd.ulVersion = SECBUFFER_VERSION;
 
     // SSPI Buf
     ib[0].BufferType = SECBUFFER_STREAM;
     ib[0].cbBuffer = inTokenLen;
     ib[0].pvBuffer = moz_xmalloc(ib[0].cbBuffer);
-    if (!ib[0].pvBuffer)
-        return NS_ERROR_OUT_OF_MEMORY;
 
     memcpy(ib[0].pvBuffer, inToken, inTokenLen);
 
     // app data
     ib[1].BufferType = SECBUFFER_DATA;
     ib[1].cbBuffer = 0;
     ib[1].pvBuffer = nullptr;
 
@@ -549,20 +537,18 @@ nsAuthSSPI::Unwrap(const void *inToken,
     if (SEC_SUCCESS(rc)) {
         // check if ib[1].pvBuffer is really just ib[0].pvBuffer, in which
         // case we can let the caller free it. Otherwise, we need to
         // clone it, and free the original
         if (ib[0].pvBuffer == ib[1].pvBuffer) {
             *outToken = ib[1].pvBuffer;
         }
         else {
-            *outToken = nsMemory::Clone(ib[1].pvBuffer, ib[1].cbBuffer);
+            *outToken = moz_xmemdup(ib[1].pvBuffer, ib[1].cbBuffer);
             free(ib[0].pvBuffer);
-            if (!*outToken)
-                return NS_ERROR_OUT_OF_MEMORY;
         }
         *outTokenLen = ib[1].cbBuffer;
     }
     else
         free(ib[0].pvBuffer);
 
     if (!SEC_SUCCESS(rc))
         return NS_ERROR_FAILURE;
@@ -617,48 +603,36 @@ nsAuthSSPI::Wrap(const void *inToken,
     ibd.pBuffers = bufs.ib;
     ibd.ulVersion = SECBUFFER_VERSION;
 
     // SSPI
     bufs.ib[0].cbBuffer = sizes.cbSecurityTrailer;
     bufs.ib[0].BufferType = SECBUFFER_TOKEN;
     bufs.ib[0].pvBuffer = moz_xmalloc(sizes.cbSecurityTrailer);
 
-    if (!bufs.ib[0].pvBuffer)
-        return NS_ERROR_OUT_OF_MEMORY;
-
     // APP Data
     bufs.ib[1].BufferType = SECBUFFER_DATA;
     bufs.ib[1].pvBuffer = moz_xmalloc(inTokenLen);
     bufs.ib[1].cbBuffer = inTokenLen;
 
-    if (!bufs.ib[1].pvBuffer)
-        return NS_ERROR_OUT_OF_MEMORY;
-
     memcpy(bufs.ib[1].pvBuffer, inToken, inTokenLen);
 
     // SSPI
     bufs.ib[2].BufferType = SECBUFFER_PADDING;
     bufs.ib[2].cbBuffer = sizes.cbBlockSize;
     bufs.ib[2].pvBuffer = moz_xmalloc(bufs.ib[2].cbBuffer);
 
-    if (!bufs.ib[2].pvBuffer)
-        return NS_ERROR_OUT_OF_MEMORY;
-
     rc = (sspi->EncryptMessage)(&mCtxt,
           confidential ? 0 : KERB_WRAP_NO_ENCRYPT,
          &ibd, 0);
 
     if (SEC_SUCCESS(rc)) {
         int len  = bufs.ib[0].cbBuffer + bufs.ib[1].cbBuffer + bufs.ib[2].cbBuffer;
         char *p = (char *) moz_xmalloc(len);
 
-        if (!p)
-            return NS_ERROR_OUT_OF_MEMORY;
-
         *outToken = (void *) p;
         *outTokenLen = len;
 
         memcpy(p, bufs.ib[0].pvBuffer, bufs.ib[0].cbBuffer);
         p += bufs.ib[0].cbBuffer;
 
         memcpy(p,bufs.ib[1].pvBuffer, bufs.ib[1].cbBuffer);
         p += bufs.ib[1].cbBuffer;
--- a/extensions/auth/nsAuthSambaNTLM.cpp
+++ b/extensions/auth/nsAuthSambaNTLM.cpp
@@ -230,19 +230,17 @@ nsAuthSambaNTLM::Init(const char *servic
 NS_IMETHODIMP
 nsAuthSambaNTLM::GetNextToken(const void *inToken,
                               uint32_t    inTokenLen,
                               void      **outToken,
                               uint32_t   *outTokenLen)
 {
     if (!inToken) {
         /* someone wants our initial message */
-        *outToken = nsMemory::Clone(mInitialMessage, mInitialMessageLen);
-        if (!*outToken)
-            return NS_ERROR_OUT_OF_MEMORY;
+        *outToken = moz_xmemdup(mInitialMessage, mInitialMessageLen);
         *outTokenLen = mInitialMessageLen;
         return NS_OK;
     }
 
     /* inToken must be a type 2 message. Get ntlm_auth to generate our response */
     char* encoded = PL_Base64Encode(static_cast<const char*>(inToken), inTokenLen, nullptr);
     if (!encoded)
         return NS_ERROR_OUT_OF_MEMORY;
@@ -261,21 +259,18 @@ nsAuthSambaNTLM::GetNextToken(const void
     if (!StringBeginsWith(line, NS_LITERAL_CSTRING("KK ")) &&
         !StringBeginsWith(line, NS_LITERAL_CSTRING("AF "))) {
         // Something went wrong. Perhaps no credentials are accessible.
         return NS_ERROR_FAILURE;
     }
     uint8_t* buf = ExtractMessage(line, outTokenLen);
     if (!buf)
         return NS_ERROR_FAILURE;
-    *outToken = nsMemory::Clone(buf, *outTokenLen);
+    *outToken = moz_xmemdup(buf, *outTokenLen);
     PR_Free(buf);
-    if (!*outToken) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
 
     // We're done. Close our file descriptors now and reap the helper
     // process.
     Shutdown();
     return NS_SUCCESS_AUTH_FINISHED;
 }
 
 NS_IMETHODIMP
--- a/extensions/auth/nsHttpNegotiateAuth.cpp
+++ b/extensions/auth/nsHttpNegotiateAuth.cpp
@@ -578,20 +578,17 @@ nsHttpNegotiateAuth::GenerateCredentials
     if (!encoded_token)
         return NS_ERROR_OUT_OF_MEMORY;
 
     LOG(("  Sending a token of length %d\n", outTokenLen));
 
     // allocate a buffer sizeof("Negotiate" + " " + b64output_token + "\0")
     const int bufsize = kNegotiateLen + 1 + strlen(encoded_token) + 1;
     *creds = (char *) moz_xmalloc(bufsize);
-    if (MOZ_UNLIKELY(!*creds))
-        rv = NS_ERROR_OUT_OF_MEMORY;
-    else
-        snprintf(*creds, bufsize, "%s %s", kNegotiate, encoded_token);
+    snprintf(*creds, bufsize, "%s %s", kNegotiate, encoded_token);
 
     PR_Free(encoded_token); // PL_Base64Encode() uses PR_Malloc().
     return rv;
 }
 
 bool
 nsHttpNegotiateAuth::TestBoolPref(const char *pref)
 {
--- a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
@@ -466,62 +466,54 @@ mozHunspell::Suggest(const nsAString& aW
   rv = ConvertCharset(aWord, charsetWord);
   NS_ENSURE_SUCCESS(rv, rv);
 
   std::vector<std::string> suggestions = mHunspell->suggest(charsetWord);
   *aSuggestionCount = static_cast<uint32_t>(suggestions.size());
 
   if (*aSuggestionCount) {
     *aSuggestions  = (char16_t **)moz_xmalloc(*aSuggestionCount * sizeof(char16_t *));
-    if (*aSuggestions) {
-      uint32_t index = 0;
-      for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
-        // If the IDL used an array of AString, we could use
-        // Encoding::DecodeWithoutBOMHandling() here.
-        // Convert the suggestion to utf16
-        Span<const char> charSrc(suggestions[index]);
-        auto src = AsBytes(charSrc);
-        CheckedInt<size_t> needed =
-          mDecoder->MaxUTF16BufferLength(src.Length());
-        if (!needed.isValid()) {
-          rv = NS_ERROR_OUT_OF_MEMORY;
-          break;
-        }
-        size_t dstLen = needed.value();
-        needed += 1;
-        needed *= sizeof(char16_t);
-        if (!needed.isValid()) {
-          rv = NS_ERROR_OUT_OF_MEMORY;
-          break;
-        }
-        (*aSuggestions)[index] = (char16_t*)moz_xmalloc(needed.value());
-        if (!((*aSuggestions)[index])) {
-          rv = NS_ERROR_OUT_OF_MEMORY;
-          break;
-        }
-        auto dst = MakeSpan((*aSuggestions)[index], dstLen);
-        uint32_t result;
-        size_t read;
-        size_t written;
-        bool hadErrors;
-        Tie(result, read, written, hadErrors) =
-          mDecoder->DecodeToUTF16(src, dst, true);
-        MOZ_ASSERT(result == kInputEmpty);
-        MOZ_ASSERT(read == src.Length());
-        MOZ_ASSERT(written <= dstLen);
-        Unused << hadErrors;
-        (*aSuggestions)[index][written] = 0;
-        mDecoder->Encoding()->NewDecoderWithoutBOMHandlingInto(*mDecoder);
+    uint32_t index = 0;
+    for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
+      // If the IDL used an array of AString, we could use
+      // Encoding::DecodeWithoutBOMHandling() here.
+      // Convert the suggestion to utf16
+      Span<const char> charSrc(suggestions[index]);
+      auto src = AsBytes(charSrc);
+      CheckedInt<size_t> needed =
+        mDecoder->MaxUTF16BufferLength(src.Length());
+      if (!needed.isValid()) {
+        rv = NS_ERROR_OUT_OF_MEMORY;
+        break;
       }
+      size_t dstLen = needed.value();
+      needed += 1;
+      needed *= sizeof(char16_t);
+      if (!needed.isValid()) {
+        rv = NS_ERROR_OUT_OF_MEMORY;
+        break;
+      }
+      (*aSuggestions)[index] = (char16_t*)moz_xmalloc(needed.value());
+      auto dst = MakeSpan((*aSuggestions)[index], dstLen);
+      uint32_t result;
+      size_t read;
+      size_t written;
+      bool hadErrors;
+      Tie(result, read, written, hadErrors) =
+        mDecoder->DecodeToUTF16(src, dst, true);
+      MOZ_ASSERT(result == kInputEmpty);
+      MOZ_ASSERT(read == src.Length());
+      MOZ_ASSERT(written <= dstLen);
+      Unused << hadErrors;
+      (*aSuggestions)[index][written] = 0;
+      mDecoder->Encoding()->NewDecoderWithoutBOMHandlingInto(*mDecoder);
+    }
 
-      if (NS_FAILED(rv))
-        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the char16_t strings up to the point at which the error occurred
-    }
-    else // if (*aSuggestions)
-      rv = NS_ERROR_OUT_OF_MEMORY;
+    if (NS_FAILED(rv))
+      NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the char16_t strings up to the point at which the error occurred
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 mozHunspell::Observe(nsISupports* aSubj, const char *aTopic,
                     const char16_t *aData)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6dcf942ac1c6378b9b2b3b954258288fbe5be8b0
GIT binary patch
literal 220
zc${NkV7S8o1WZ7jn^#ig9^@Dq5gDbxfCLhgiwhX=f^XLt7(w)9UHs~>0;c4Q#1tSs
r2Z(jDLxP-v^a&sqDNZvs0;^y|(}9JbTv}8H<*_g@h&!ge`2QaOr^*zi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2d8efe536bcf863ae3adb6b3656c5cb33cead84e
GIT binary patch
literal 372
zc${NkU@Tz(0wy3XPR=U|a(7aQh>TKTKmv)$#RUv_!MAG+j3D~5E`D`b0ef;rVhWJH
z0mM2*K+72z7+HX9k#q=K0>n;&uysJ}qL3hGAlm`R=1YgL1Hft^Y>-(3#c9SyVAC1V
zY{SAw_&0wZ1B1mk1_tJSgjmuv28QkJ3=9%?5MnBe7#R4Q85p)5N-ixbgPFwikAVS+
U5A=h$W7>=V|B=Li!TkR}06mQ^*8l(j
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1626458464567e179901dfdb4401f9125d7a09cc
GIT binary patch
literal 732
zc$}?}y-Px26vls73xkFh!Jr_ah6a;ph#(uZB%&b@2aOEWz!pEaS*t}wgG18L*kJt!
zQGsJM)g)0k_y;%yZ4MRO&b@x#2&W$I!+GBGp8KBX9I#Xo^a+!xtQuJMIYZ%fCtZlf
zcQW)u{S8HrFH^ni{)A1Hh7v16d!nJ=bsaOb@vvPD1{OuzMNcLg+N0}OLvM*5_0IUF
zMehqYIy0m%V6G0<(@rjS4tFOoT<zp0iZFBtxA&Q-8l|-q<>m^dkcM#^Y=>cKQ{o6L
z#7uR#K4H}h4<VQr->DLOox!W8U1!mGy@FC1koUxQzccCe8U3wRqe9m~;gRrBn!Dn=
z>RxkCQZf6iY0#BZEQ<L|q_tLuAKZEHmm%VStlZ>f#$pXhZYXD=R^r$HmNoNP$wAw{
q;n8=1@*&<!-!k7N91mKX=4qP{<g|bOOul53n%4GZpzvh!JqAA(sff4$
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2db6991c2323f9a4999c09c4d617dceffe4b5761
GIT binary patch
literal 744
zc${NkV0ys-1S~+Dn^#g4<nE*p5gDbxfCLhgiwhX=f^XLt7(w)9UHs~>0wzZzCj%fo
z2Z(<;894&kj5B~ZAUCbV2&90SnVA7%J`%vjX9hxs`v3p`4}CJ%$x#8~cd+k3Y)~95
z0OBh^&k7`$7L`GL4pd=w8l<Nnu_zHN0*XvV<?RfN2Q`3N&oeOCsxdJ1RWmR&FJ@qP
zxE7mU2oQH=V9@JkU~s+2zz{3Wz)%v)z|g&jfngCajqK86V7OSq!0=)hD6Emp0NN(*
znD*lTe<U$RrU(=@ObiVF|1&c&VMby7f1(hw*^G0M{0cIXF=;*nqfQ|M!#-^W2CoKe
G{sREW>dXoN
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c13db9b200253583956b3d8b43c666c5dde23001
GIT binary patch
literal 1809
zc${NkU>9Tn0u~@HPR=U|a(7bjNla2;Kmv)$#RUv_!MAG+j3D~5E`D`b0i&allL3&P
zz`(%Pn44B&2ohvwW@dnxiL4R}pOJ}~g_Vt+gOiJ!hnJ6EKu}0nL{v;%LQ+avMpjN<
zK~YIrMO95*LsLszM^{hZz|hFp#MI2(!qUpx#@5c>!O_Xt#nsK-!_&*#$Jft4ATTI6
zBs45MA~GsECN?fUAu%aAB{eNQBQq;ICpRy@ps=X8q_nKOqOz*GrnauWp|PpCrM0cS
zqqD2Kr?;<v!o*3Fr%atTea6gLv**m6H-EvxMT?g#UABD1%2lh^tX;Q$!^TaUw`|?E
zeaFsSyZ7wfxBtMwLx+zXJ$C%W$y2A#oIQ8`!o^FMuUx%${l?8(x9{A&cmKh|M~|O8
zefIpt%U7@8ynXln!^cmbzkL1n{m0K=zyJLG_kYy?Bi#S>)J7vcKu7&QqWup5eEBhH
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -52,17 +52,17 @@
 
 #include "MainThreadUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
-#include "nsISimpleEnumerator.h"
+#include "nsIDirectoryEnumerator.h"
 #include "nsCharTraits.h"
 #include "nsCocoaFeatures.h"
 #include "nsCocoaUtils.h"
 #include "gfxFontConstants.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/FontPropertyTypes.h"
@@ -1872,17 +1872,17 @@ gfxMacPlatformFontList::CreateFontFamily
 void
 gfxMacPlatformFontList::ActivateFontsFromDir(nsIFile* aDir)
 {
     bool isDir;
     if (NS_FAILED(aDir->IsDirectory(&isDir)) || !isDir) {
         return;
     }
 
-    nsCOMPtr<nsISimpleEnumerator> e;
+    nsCOMPtr<nsIDirectoryEnumerator> e;
     if (NS_FAILED(aDir->GetDirectoryEntries(getter_AddRefs(e)))) {
         return;
     }
 
     CFMutableArrayRef urls =
         ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
 
     bool hasMore;
deleted file mode 100644
--- a/gfx/ycbcr/QuellGccWarnings.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
---- a/gfx/ycbcr/yuv_convert.cpp
-+++ b/gfx/ycbcr/yuv_convert.cpp
-@@ -337,16 +337,17 @@ void ScaleYCbCrToRGB32(const uint* yplan
-                                          source_dx_uv >> kFractionBits);
-         }
-       }
-       else {
-         ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
-                              dest_pixel, width, source_dx);
-       }
- #else
-+      (void)source_dx_uv;
-       ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
-                          dest_pixel, width, source_dx);
- #endif
-     }
-   }
-   // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
-   if (has_mmx)
-     EMMS();
-diff --git a/gfx/ycbcr/yuv_row.h b/gfx/ycbcr/yuv_row.h
---- a/gfx/ycbcr/yuv_row.h
-+++ b/gfx/ycbcr/yuv_row.h
-@@ -129,14 +129,14 @@ extern SIMD_ALIGNED(int16 kCoefficientsR
- #if defined(ARCH_CPU_X86) && !defined(ARCH_CPU_X86_64)
- #if defined(_MSC_VER)
- #define EMMS() __asm emms
- #pragma warning(disable: 4799)
- #else
- #define EMMS() asm("emms")
- #endif
- #else
--#define EMMS()
-+#define EMMS() ((void)0)
- #endif
- 
- }  // extern "C"
- 
- #endif  // MEDIA_BASE_YUV_ROW_H_
--- a/gfx/ycbcr/README
+++ b/gfx/ycbcr/README
@@ -1,31 +1,8 @@
 This color conversion code is from the Chromium open source project available here:
 
 http://code.google.com/chromium/
 
 The code comes from svn revision 63840 on 2010-10-26.
 
-If you just want to check out this individual directory, use:
-
-svn co -r 63840 http://src.chromium.org/svn/trunk/src/media/base
-
-The code was copied from a Chromium svn checkout using the 'update.sh' script which then applies patches for our build and to add dynamic CPU detection.
-
-convert.patch contains the following changes:
-
-  * Change Chromium code to build using Mozilla build system.
-  * Add runtime CPU detection for MMX
-  * Move default C implementation to work on all platforms.
-  * Change Chromium code to allow a picture region.
-  * The YUV conversion will convert within this picture region only.
-  * Add YCbCr 4:4:4 support
-  * Bug 619178 - Update CPU detection in yuv_convert to new SSE.h interface.
-  * Bug 616778 - Split yuv_convert FilterRows vectorized code into separate files so it can
-    be properly guarded with cpuid() calls.
-
-win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version
-
-TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes.
-
-QuellGccWarnings.patch: Bug 711895 - Avoid some GCC compilation warnings.
-
-clang-cl-workaround.patch: Bug 1422368 - Work around a clang-cl unresolved symbol bug.
+It has been superseded upstream by libyuv (which is spawned off it). Bug 791941 is about
+trying to replace this code with libyuv.
deleted file mode 100644
--- a/gfx/ycbcr/TypeFromSize.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
---- a/gfx/ycbcr/yuv_convert.cpp
-+++ b/gfx/ycbcr/yuv_convert.cpp
-@@ -26,16 +26,32 @@ namespace mozilla {
- 
- namespace gfx {
-  
- // 16.16 fixed point arithmetic
- const int kFractionBits = 16;
- const int kFractionMax = 1 << kFractionBits;
- const int kFractionMask = ((1 << kFractionBits) - 1);
- 
-+YUVType TypeFromSize(int ywidth, 
-+                     int yheight, 
-+                     int cbcrwidth, 
-+                     int cbcrheight)
-+{
-+  if (ywidth == cbcrwidth && yheight == cbcrheight) {
-+    return YV24;
-+  }
-+  else if (ywidth / 2 == cbcrwidth && yheight == cbcrheight) {
-+    return YV16;
-+  }
-+  else {
-+    return YV12;
-+  }
-+}
-+
- // Convert a frame of YUV to 32 bit ARGB.
- void ConvertYCbCrToRGB32(const uint8* y_buf,
-                          const uint8* u_buf,
-                          const uint8* v_buf,
-                          uint8* rgb_buf,
-                          int pic_x,
-                          int pic_y,
-                          int pic_width,
-diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
---- a/gfx/ycbcr/yuv_convert.h
-+++ b/gfx/ycbcr/yuv_convert.h
-@@ -36,16 +36,18 @@ enum Rotate {
- // Filter affects how scaling looks.
- enum ScaleFilter {
-   FILTER_NONE = 0,        // No filter (point sampled).
-   FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
-   FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
-   FILTER_BILINEAR = 3     // Bilinear filter.
- };
- 
-+YUVType TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
-+
- // Convert a frame of YUV to 32 bit ARGB.
- // Pass in YV16/YV12 depending on source format
- void ConvertYCbCrToRGB32(const uint8* yplane,
-                          const uint8* uplane,
-                          const uint8* vplane,
-                          uint8* rgbframe,
-                          int pic_x,
-                          int pic_y,
--- a/gfx/ycbcr/chromium_types.h
+++ b/gfx/ycbcr/chromium_types.h
@@ -34,17 +34,17 @@
 #elif defined(__sparc)
 #define ARCH_CPU_SPARC_FAMILY 1
 #define ARCH_CPU_SPARC 1
 #define ARCH_CPU_32_BITS 1
 #elif defined(__sparcv9)
 #define ARCH_CPU_SPARC_FAMILY 1
 #define ARCH_CPU_SPARC 1
 #define ARCH_CPU_64_BITS 1
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(_M_ARM64)
 #define ARCH_CPU_AARCH64_FAMILY 1
 #define ARCH_CPU_AARCH64 1
 #define ARCH_CPU_64_BITS 1
 #else
 #warning Please add support for your architecture in chromium_types.h
 #endif
 
 #endif // GFX_CHROMIUMTYPES_H
deleted file mode 100644
--- a/gfx/ycbcr/clang-cl-workaround.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_row_win.cpp b/gfx/ycbcr/yuv_row_win.cpp
---- a/gfx/ycbcr/yuv_row_win.cpp
-+++ b/gfx/ycbcr/yuv_row_win.cpp
-@@ -7,19 +7,21 @@
- 
- #define kCoefficientsRgbU kCoefficientsRgbY + 2048
- #define kCoefficientsRgbV kCoefficientsRgbY + 4096
- 
- extern "C" {
- 
- #if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
- #if defined(__clang__)
--// clang-cl may erroneously discard the symbol `kCoefficientsRgbY`
--// https://bugs.llvm.org/show_bug.cgi?id=35290
--volatile auto keep_kCoefficientsRgbY_alive = &kCoefficientsRgbY;
-+// clang-cl has a bug where it doesn't mangle names in inline asm
-+// so let's do the mangling in the preprocessor (ugh)
-+// (but we still need to declare a dummy extern for the parser)
-+extern void* _kCoefficientsRgbY;
-+#define kCoefficientsRgbY _kCoefficientsRgbY
- #endif
- 
- __declspec(naked)
- void FastConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-                                   const uint8* u_buf,
-                                   const uint8* v_buf,
-                                   uint8* rgb_buf,
-                                   int width) {
deleted file mode 100644
--- a/gfx/ycbcr/convert.patch
+++ /dev/null
@@ -1,3143 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
---- a/gfx/ycbcr/yuv_convert.cpp
-+++ b/gfx/ycbcr/yuv_convert.cpp
-@@ -6,145 +6,102 @@
- // http://www.fourcc.org/yuv.php
- // The actual conversion is best described here
- // http://en.wikipedia.org/wiki/YUV
- // An article on optimizing YUV conversion using tables instead of multiplies
- // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
- //
- // YV12 is a full plane of Y and a half height, half width chroma planes
- // YV16 is a full plane of Y and a full height, half width chroma planes
-+// YV24 is a full plane of Y and a full height, full width chroma planes
- //
- // ARGB pixel format is output, which on little endian is stored as BGRA.
- // The alpha is set to 255, allowing the application to use RGBA or RGB32.
- 
--#include "media/base/yuv_convert.h"
-+#include "yuv_convert.h"
- 
- // Header for low level row functions.
--#include "media/base/yuv_row.h"
--
--#if USE_MMX
--#if defined(_MSC_VER)
--#include <intrin.h>
--#else
--#include <mmintrin.h>
--#endif
--#endif
--
--#if USE_SSE2
--#include <emmintrin.h>
--#endif
--
--namespace media {
--
-+#include "yuv_row.h"
-+#include "mozilla/SSE.h"
-+
-+namespace mozilla {
-+
-+namespace gfx {
-+ 
- // 16.16 fixed point arithmetic
- const int kFractionBits = 16;
- const int kFractionMax = 1 << kFractionBits;
- const int kFractionMask = ((1 << kFractionBits) - 1);
- 
- // Convert a frame of YUV to 32 bit ARGB.
--void ConvertYUVToRGB32(const uint8* y_buf,
--                       const uint8* u_buf,
--                       const uint8* v_buf,
--                       uint8* rgb_buf,
--                       int width,
--                       int height,
--                       int y_pitch,
--                       int uv_pitch,
--                       int rgb_pitch,
--                       YUVType yuv_type) {
--  unsigned int y_shift = yuv_type;
--  for (int y = 0; y < height; ++y) {
--    uint8* rgb_row = rgb_buf + y * rgb_pitch;
--    const uint8* y_ptr = y_buf + y * y_pitch;
--    const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch;
--    const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch;
--
--    FastConvertYUVToRGB32Row(y_ptr,
--                             u_ptr,
--                             v_ptr,
--                             rgb_row,
--                             width);
--  }
-+void ConvertYCbCrToRGB32(const uint8* y_buf,
-+                         const uint8* u_buf,
-+                         const uint8* v_buf,
-+                         uint8* rgb_buf,
-+                         int pic_x,
-+                         int pic_y,
-+                         int pic_width,
-+                         int pic_height,
-+                         int y_pitch,
-+                         int uv_pitch,
-+                         int rgb_pitch,
-+                         YUVType yuv_type) {
-+  unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
-+  unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
-+  // Test for SSE because the optimized code uses movntq, which is not part of MMX.
-+  bool has_sse = supports_mmx() && supports_sse();
-+  // There is no optimized YV24 SSE routine so we check for this and
-+  // fall back to the C code.
-+  has_sse &= yuv_type != YV24;
-+  bool odd_pic_x = yuv_type != YV24 && pic_x % 2 != 0;
-+  int x_width = odd_pic_x ? pic_width - 1 : pic_width;
-+
-+  for (int y = pic_y; y < pic_height + pic_y; ++y) {
-+    uint8* rgb_row = rgb_buf + (y - pic_y) * rgb_pitch;
-+    const uint8* y_ptr = y_buf + y * y_pitch + pic_x;
-+    const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);
-+    const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch + (pic_x >> x_shift);
-+
-+    if (odd_pic_x) {
-+      // Handle the single odd pixel manually and use the
-+      // fast routines for the remaining.
-+      FastConvertYUVToRGB32Row_C(y_ptr++,
-+                                 u_ptr++,
-+                                 v_ptr++,
-+                                 rgb_row,
-+                                 1,
-+                                 x_shift);
-+      rgb_row += 4;
-+    }
-+
-+    if (has_sse) {
-+      FastConvertYUVToRGB32Row(y_ptr,
-+                               u_ptr,
-+                               v_ptr,
-+                               rgb_row,
-+                               x_width);
-+    }
-+    else {
-+      FastConvertYUVToRGB32Row_C(y_ptr,
-+                                 u_ptr,
-+                                 v_ptr,
-+                                 rgb_row,
-+                                 x_width,
-+                                 x_shift);
-+    }
-+  }
- 
-   // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
--  EMMS();
--}
--
--#if USE_SSE2
--// FilterRows combines two rows of the image using linear interpolation.
--// SSE2 version does 16 pixels at a time
--
--static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
--                       int source_width, int source_y_fraction) {
--  __m128i zero = _mm_setzero_si128();
--  __m128i y1_fraction = _mm_set1_epi16(source_y_fraction);
--  __m128i y0_fraction = _mm_set1_epi16(256 - source_y_fraction);
--
--  const __m128i* y0_ptr128 = reinterpret_cast<const __m128i*>(y0_ptr);
--  const __m128i* y1_ptr128 = reinterpret_cast<const __m128i*>(y1_ptr);
--  __m128i* dest128 = reinterpret_cast<__m128i*>(ybuf);
--  __m128i* end128 = reinterpret_cast<__m128i*>(ybuf + source_width);
--
--  do {
--    __m128i y0 = _mm_loadu_si128(y0_ptr128);
--    __m128i y1 = _mm_loadu_si128(y1_ptr128);
--    __m128i y2 = _mm_unpackhi_epi8(y0, zero);
--    __m128i y3 = _mm_unpackhi_epi8(y1, zero);
--    y0 = _mm_unpacklo_epi8(y0, zero);
--    y1 = _mm_unpacklo_epi8(y1, zero);
--    y0 = _mm_mullo_epi16(y0, y0_fraction);
--    y1 = _mm_mullo_epi16(y1, y1_fraction);
--    y2 = _mm_mullo_epi16(y2, y0_fraction);
--    y3 = _mm_mullo_epi16(y3, y1_fraction);
--    y0 = _mm_add_epi16(y0, y1);
--    y2 = _mm_add_epi16(y2, y3);
--    y0 = _mm_srli_epi16(y0, 8);
--    y2 = _mm_srli_epi16(y2, 8);
--    y0 = _mm_packus_epi16(y0, y2);
--    *dest128++ = y0;
--    ++y0_ptr128;
--    ++y1_ptr128;
--  } while (dest128 < end128);
--}
--#elif USE_MMX
--// MMX version does 8 pixels at a time
--static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
--                       int source_width, int source_y_fraction) {
--  __m64 zero = _mm_setzero_si64();
--  __m64 y1_fraction = _mm_set1_pi16(source_y_fraction);
--  __m64 y0_fraction = _mm_set1_pi16(256 - source_y_fraction);
--
--  const __m64* y0_ptr64 = reinterpret_cast<const __m64*>(y0_ptr);
--  const __m64* y1_ptr64 = reinterpret_cast<const __m64*>(y1_ptr);
--  __m64* dest64 = reinterpret_cast<__m64*>(ybuf);
--  __m64* end64 = reinterpret_cast<__m64*>(ybuf + source_width);
--
--  do {
--    __m64 y0 = *y0_ptr64++;
--    __m64 y1 = *y1_ptr64++;
--    __m64 y2 = _mm_unpackhi_pi8(y0, zero);
--    __m64 y3 = _mm_unpackhi_pi8(y1, zero);
--    y0 = _mm_unpacklo_pi8(y0, zero);
--    y1 = _mm_unpacklo_pi8(y1, zero);
--    y0 = _mm_mullo_pi16(y0, y0_fraction);
--    y1 = _mm_mullo_pi16(y1, y1_fraction);
--    y2 = _mm_mullo_pi16(y2, y0_fraction);
--    y3 = _mm_mullo_pi16(y3, y1_fraction);
--    y0 = _mm_add_pi16(y0, y1);
--    y2 = _mm_add_pi16(y2, y3);
--    y0 = _mm_srli_pi16(y0, 8);
--    y2 = _mm_srli_pi16(y2, 8);
--    y0 = _mm_packs_pu16(y0, y2);
--    *dest64++ = y0;
--  } while (dest64 < end64);
--}
--#else  // no MMX or SSE2
-+  if (has_sse)
-+    EMMS();
-+}
-+
- // C version does 8 at a time to mimic MMX code
--static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
--                       int source_width, int source_y_fraction) {
-+static void FilterRows_C(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
-+                         int source_width, int source_y_fraction) {
-   int y1_fraction = source_y_fraction;
-   int y0_fraction = 256 - y1_fraction;
-   uint8* end = ybuf + source_width;
-   do {
-     ybuf[0] = (y0_ptr[0] * y0_fraction + y1_ptr[0] * y1_fraction) >> 8;
-     ybuf[1] = (y0_ptr[1] * y0_fraction + y1_ptr[1] * y1_fraction) >> 8;
-     ybuf[2] = (y0_ptr[2] * y0_fraction + y1_ptr[2] * y1_fraction) >> 8;
-     ybuf[3] = (y0_ptr[3] * y0_fraction + y1_ptr[3] * y1_fraction) >> 8;
-@@ -152,46 +140,77 @@ static void FilterRows(uint8* ybuf, cons
-     ybuf[5] = (y0_ptr[5] * y0_fraction + y1_ptr[5] * y1_fraction) >> 8;
-     ybuf[6] = (y0_ptr[6] * y0_fraction + y1_ptr[6] * y1_fraction) >> 8;
-     ybuf[7] = (y0_ptr[7] * y0_fraction + y1_ptr[7] * y1_fraction) >> 8;
-     y0_ptr += 8;
-     y1_ptr += 8;
-     ybuf += 8;
-   } while (ybuf < end);
- }
--#endif
-+
-+#ifdef MOZILLA_MAY_SUPPORT_MMX
-+void FilterRows_MMX(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
-+                    int source_width, int source_y_fraction);
-+#endif
-+
-+#ifdef MOZILLA_MAY_SUPPORT_SSE2
-+void FilterRows_SSE2(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
-+                     int source_width, int source_y_fraction);
-+#endif
-+
-+static inline void FilterRows(uint8* ybuf, const uint8* y0_ptr,
-+                              const uint8* y1_ptr, int source_width,
-+                              int source_y_fraction) {
-+#ifdef MOZILLA_MAY_SUPPORT_SSE2
-+  if (mozilla::supports_sse2()) {
-+    FilterRows_SSE2(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
-+    return;
-+  }
-+#endif
-+
-+#ifdef MOZILLA_MAY_SUPPORT_MMX
-+  if (mozilla::supports_mmx()) {
-+    FilterRows_MMX(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
-+    return;
-+  }
-+#endif
-+
-+  FilterRows_C(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
-+}
- 
- 
- // Scale a frame of YUV to 32 bit ARGB.
--void ScaleYUVToRGB32(const uint8* y_buf,
--                     const uint8* u_buf,
--                     const uint8* v_buf,
--                     uint8* rgb_buf,
--                     int source_width,
--                     int source_height,
--                     int width,
--                     int height,
--                     int y_pitch,
--                     int uv_pitch,
--                     int rgb_pitch,
--                     YUVType yuv_type,
--                     Rotate view_rotate,
--                     ScaleFilter filter) {
-+void ScaleYCbCrToRGB32(const uint8* y_buf,
-+                       const uint8* u_buf,
-+                       const uint8* v_buf,
-+                       uint8* rgb_buf,
-+                       int source_width,
-+                       int source_height,
-+                       int width,
-+                       int height,
-+                       int y_pitch,
-+                       int uv_pitch,
-+                       int rgb_pitch,
-+                       YUVType yuv_type,
-+                       Rotate view_rotate,
-+                       ScaleFilter filter) {
-+  bool has_mmx = supports_mmx();
-+
-   // 4096 allows 3 buffers to fit in 12k.
-   // Helps performance on CPU with 16K L1 cache.
-   // Large enough for 3830x2160 and 30" displays which are 2560x1600.
-   const int kFilterBufferSize = 4096;
-   // Disable filtering if the screen is too big (to avoid buffer overflows).
-   // This should never happen to regular users: they don't have monitors
-   // wider than 4096 pixels.
-   // TODO(fbarchard): Allow rotated videos to filter.
-   if (source_width > kFilterBufferSize || view_rotate)
-     filter = FILTER_NONE;
- 
--  unsigned int y_shift = yuv_type;
-+  unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
-   // Diagram showing origin and direction of source sampling.
-   // ->0   4<-
-   // 7       3
-   //
-   // 6       5
-   // ->1   2<-
-   // Rotations that start at right side of image.
-   if ((view_rotate == ROTATE_180) ||
-@@ -276,17 +295,17 @@ void ScaleYUVToRGB32(const uint8* y_buf,
-     int source_uv_fraction =
-         ((source_y_subpixel >> y_shift) & kFractionMask) >> 8;
- 
-     const uint8* y_ptr = y0_ptr;
-     const uint8* u_ptr = u0_ptr;
-     const uint8* v_ptr = v0_ptr;
-     // Apply vertical filtering if necessary.
-     // TODO(fbarchard): Remove memcpy when not necessary.
--    if (filter & media::FILTER_BILINEAR_V) {
-+    if (filter & mozilla::gfx::FILTER_BILINEAR_V) {
-       if (yscale_fixed != kFractionMax &&
-           source_y_fraction && ((source_y + 1) < source_height)) {
-         FilterRows(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
-       } else {
-         memcpy(ybuf, y0_ptr, source_width);
-       }
-       y_ptr = ybuf;
-       ybuf[source_width] = ybuf[source_width-1];
-@@ -303,44 +322,50 @@ void ScaleYUVToRGB32(const uint8* y_buf,
-       u_ptr = ubuf;
-       v_ptr = vbuf;
-       ubuf[uv_source_width] = ubuf[uv_source_width - 1];
-       vbuf[uv_source_width] = vbuf[uv_source_width - 1];
-     }
-     if (source_dx == kFractionMax) {  // Not scaled
-       FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
-                                dest_pixel, width);
--    } else {
--      if (filter & FILTER_BILINEAR_H) {
-+    } else if (filter & FILTER_BILINEAR_H) {
-         LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
-                                  dest_pixel, width, source_dx);
-     } else {
- // Specialized scalers and rotation.
--#if USE_MMX && defined(_MSC_VER)
-+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86) && !defined(__clang__)
-+      if(mozilla::supports_sse()) {
-         if (width == (source_width * 2)) {
--          DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
--                              dest_pixel, width);
-+          DoubleYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
-+                                  dest_pixel, width);
-         } else if ((source_dx & kFractionMask) == 0) {
-           // Scaling by integer scale factor. ie half.
--          ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
--                               dest_pixel, width,
--                               source_dx >> kFractionBits);
-+          ConvertYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
-+                                   dest_pixel, width,
-+                                   source_dx >> kFractionBits);
-         } else if (source_dx_uv == source_dx) {  // Not rotated.
-           ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
-                              dest_pixel, width, source_dx);
-         } else {
--          RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
--                                     dest_pixel, width,
--                                     source_dx >> kFractionBits,
--                                     source_dx_uv >> kFractionBits);
-+          RotateConvertYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,
-+                                         dest_pixel, width,
-+                                         source_dx >> kFractionBits,
-+                                         source_dx_uv >> kFractionBits);
-         }
-+      }
-+      else {
-+        ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
-+                             dest_pixel, width, source_dx);
-+      }
- #else
--        ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
--                           dest_pixel, width, source_dx);
--#endif
--      }
-+      ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
-+                         dest_pixel, width, source_dx);
-+#endif
-     }
-   }
-   // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
--  EMMS();
--}
--
--}  // namespace media
-+  if (has_mmx)
-+    EMMS();
-+}
-+
-+}  // namespace gfx
-+}  // namespace mozilla
-diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
---- a/gfx/ycbcr/yuv_convert.h
-+++ b/gfx/ycbcr/yuv_convert.h
-@@ -1,72 +1,79 @@
- // Copyright (c) 2010 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
- #ifndef MEDIA_BASE_YUV_CONVERT_H_
- #define MEDIA_BASE_YUV_CONVERT_H_
- 
--#include "base/basictypes.h"
--
--namespace media {
--
-+#include "chromium_types.h"
-+#include "gfxCore.h"
-+
-+namespace mozilla {
-+
-+namespace gfx {
-+ 
- // Type of YUV surface.
- // The value of these enums matter as they are used to shift vertical indices.
- enum YUVType {
--  YV16 = 0,           // YV16 is half width and full height chroma channels.
--  YV12 = 1,           // YV12 is half width and half height chroma channels.
-+  YV12 = 0,           // YV12 is half width and half height chroma channels.
-+  YV16 = 1,           // YV16 is half width and full height chroma channels.
-+  YV24 = 2            // YV24 is full width and full height chroma channels.
- };
- 
- // Mirror means flip the image horizontally, as in looking in a mirror.
- // Rotate happens after mirroring.
- enum Rotate {
-   ROTATE_0,           // Rotation off.
-   ROTATE_90,          // Rotate clockwise.
-   ROTATE_180,         // Rotate upside down.
-   ROTATE_270,         // Rotate counter clockwise.
-   MIRROR_ROTATE_0,    // Mirror horizontally.
-   MIRROR_ROTATE_90,   // Mirror then Rotate clockwise.
-   MIRROR_ROTATE_180,  // Mirror vertically.
--  MIRROR_ROTATE_270,  // Transpose.
-+  MIRROR_ROTATE_270   // Transpose.
- };
- 
- // Filter affects how scaling looks.
- enum ScaleFilter {
-   FILTER_NONE = 0,        // No filter (point sampled).
-   FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
-   FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
--  FILTER_BILINEAR = 3,    // Bilinear filter.
-+  FILTER_BILINEAR = 3     // Bilinear filter.
- };
- 
- // Convert a frame of YUV to 32 bit ARGB.
- // Pass in YV16/YV12 depending on source format
--void ConvertYUVToRGB32(const uint8* yplane,
--                       const uint8* uplane,
--                       const uint8* vplane,
--                       uint8* rgbframe,
--                       int width,
--                       int height,
--                       int ystride,
--                       int uvstride,
--                       int rgbstride,
--                       YUVType yuv_type);
-+void ConvertYCbCrToRGB32(const uint8* yplane,
-+                         const uint8* uplane,
-+                         const uint8* vplane,
-+                         uint8* rgbframe,
-+                         int pic_x,
-+                         int pic_y,
-+                         int pic_width,
-+                         int pic_height,
-+                         int ystride,
-+                         int uvstride,
-+                         int rgbstride,
-+                         YUVType yuv_type);
- 
- // Scale a frame of YUV to 32 bit ARGB.
- // Supports rotation and mirroring.
--void ScaleYUVToRGB32(const uint8* yplane,
--                     const uint8* uplane,
--                     const uint8* vplane,
--                     uint8* rgbframe,
--                     int source_width,
--                     int source_height,
--                     int width,
--                     int height,
--                     int ystride,
--                     int uvstride,
--                     int rgbstride,
--                     YUVType yuv_type,
--                     Rotate view_rotate,
--                     ScaleFilter filter);
--
--}  // namespace media
--
-+void ScaleYCbCrToRGB32(const uint8* yplane,
-+                       const uint8* uplane,
-+                       const uint8* vplane,
-+                       uint8* rgbframe,
-+                       int source_width,
-+                       int source_height,
-+                       int width,
-+                       int height,
-+                       int ystride,
-+                       int uvstride,
-+                       int rgbstride,
-+                       YUVType yuv_type,
-+                       Rotate view_rotate,
-+                       ScaleFilter filter);
-+
-+}  // namespace gfx
-+}  // namespace mozilla
-+ 
- #endif  // MEDIA_BASE_YUV_CONVERT_H_
-diff --git a/gfx/ycbcr/yuv_convert_mmx.cpp b/gfx/ycbcr/yuv_convert_mmx.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/ycbcr/yuv_convert_mmx.cpp
-@@ -0,0 +1,45 @@
-+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include <mmintrin.h>
-+#include "yuv_row.h"
-+
-+namespace mozilla {
-+namespace gfx {
-+
-+// FilterRows combines two rows of the image using linear interpolation.
-+// MMX version does 8 pixels at a time.
-+void FilterRows_MMX(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
-+                    int source_width, int source_y_fraction) {
-+  __m64 zero = _mm_setzero_si64();
-+  __m64 y1_fraction = _mm_set1_pi16(source_y_fraction);
-+  __m64 y0_fraction = _mm_set1_pi16(256 - source_y_fraction);
-+
-+  const __m64* y0_ptr64 = reinterpret_cast<const __m64*>(y0_ptr);
-+  const __m64* y1_ptr64 = reinterpret_cast<const __m64*>(y1_ptr);
-+  __m64* dest64 = reinterpret_cast<__m64*>(ybuf);
-+  __m64* end64 = reinterpret_cast<__m64*>(ybuf + source_width);
-+
-+  do {
-+    __m64 y0 = *y0_ptr64++;
-+    __m64 y1 = *y1_ptr64++;
-+    __m64 y2 = _mm_unpackhi_pi8(y0, zero);
-+    __m64 y3 = _mm_unpackhi_pi8(y1, zero);
-+    y0 = _mm_unpacklo_pi8(y0, zero);
-+    y1 = _mm_unpacklo_pi8(y1, zero);
-+    y0 = _mm_mullo_pi16(y0, y0_fraction);
-+    y1 = _mm_mullo_pi16(y1, y1_fraction);
-+    y2 = _mm_mullo_pi16(y2, y0_fraction);
-+    y3 = _mm_mullo_pi16(y3, y1_fraction);
-+    y0 = _mm_add_pi16(y0, y1);
-+    y2 = _mm_add_pi16(y2, y3);
-+    y0 = _mm_srli_pi16(y0, 8);
-+    y2 = _mm_srli_pi16(y2, 8);
-+    y0 = _mm_packs_pu16(y0, y2);
-+    *dest64++ = y0;
-+  } while (dest64 < end64);
-+}
-+
-+}
-+}
-diff --git a/gfx/ycbcr/yuv_convert_sse2.cpp b/gfx/ycbcr/yuv_convert_sse2.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/ycbcr/yuv_convert_sse2.cpp
-@@ -0,0 +1,47 @@
-+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include <emmintrin.h>
-+#include "yuv_row.h"
-+
-+namespace mozilla {
-+namespace gfx {
-+
-+// FilterRows combines two rows of the image using linear interpolation.
-+// SSE2 version does 16 pixels at a time.
-+void FilterRows_SSE2(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
-+                     int source_width, int source_y_fraction) {
-+  __m128i zero = _mm_setzero_si128();
-+  __m128i y1_fraction = _mm_set1_epi16(source_y_fraction);
-+  __m128i y0_fraction = _mm_set1_epi16(256 - source_y_fraction);
-+
-+  const __m128i* y0_ptr128 = reinterpret_cast<const __m128i*>(y0_ptr);
-+  const __m128i* y1_ptr128 = reinterpret_cast<const __m128i*>(y1_ptr);
-+  __m128i* dest128 = reinterpret_cast<__m128i*>(ybuf);
-+  __m128i* end128 = reinterpret_cast<__m128i*>(ybuf + source_width);
-+
-+  do {
-+    __m128i y0 = _mm_loadu_si128(y0_ptr128);
-+    __m128i y1 = _mm_loadu_si128(y1_ptr128);
-+    __m128i y2 = _mm_unpackhi_epi8(y0, zero);
-+    __m128i y3 = _mm_unpackhi_epi8(y1, zero);
-+    y0 = _mm_unpacklo_epi8(y0, zero);
-+    y1 = _mm_unpacklo_epi8(y1, zero);
-+    y0 = _mm_mullo_epi16(y0, y0_fraction);
-+    y1 = _mm_mullo_epi16(y1, y1_fraction);
-+    y2 = _mm_mullo_epi16(y2, y0_fraction);
-+    y3 = _mm_mullo_epi16(y3, y1_fraction);
-+    y0 = _mm_add_epi16(y0, y1);
-+    y2 = _mm_add_epi16(y2, y3);
-+    y0 = _mm_srli_epi16(y0, 8);
-+    y2 = _mm_srli_epi16(y2, 8);
-+    y0 = _mm_packus_epi16(y0, y2);
-+    *dest128++ = y0;
-+    ++y0_ptr128;
-+    ++y1_ptr128;
-+  } while (dest128 < end128);
-+}
-+
-+}
-+}
-diff --git a/gfx/ycbcr/yuv_row.h b/gfx/ycbcr/yuv_row.h
---- a/gfx/ycbcr/yuv_row.h
-+++ b/gfx/ycbcr/yuv_row.h
-@@ -5,109 +5,133 @@
- // yuv_row internal functions to handle YUV conversion and scaling to RGB.
- // These functions are used from both yuv_convert.cc and yuv_scale.cc.
- 
- // TODO(fbarchard): Write function that can handle rotation and scaling.
- 
- #ifndef MEDIA_BASE_YUV_ROW_H_
- #define MEDIA_BASE_YUV_ROW_H_
- 
--#include "base/basictypes.h"
-+#include "chromium_types.h"
- 
- extern "C" {
- // Can only do 1x.
- // This is the second fastest of the scalers.
- void FastConvertYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width);
- 
--// Can do 1x, half size or any scale down by an integer amount.
--// Step can be negative (mirroring, rotate 180).
--// This is the third fastest of the scalers.
--void ConvertYUVToRGB32Row(const uint8* y_buf,
--                          const uint8* u_buf,
--                          const uint8* v_buf,
--                          uint8* rgb_buf,
--                          int width,
--                          int step);
--
--// Rotate is like Convert, but applies different step to Y versus U and V.
--// This allows rotation by 90 or 270, by stepping by stride.
--// This is the forth fastest of the scalers.
--void RotateConvertYUVToRGB32Row(const uint8* y_buf,
-+void FastConvertYUVToRGB32Row_C(const uint8* y_buf,
-                                 const uint8* u_buf,
-                                 const uint8* v_buf,
-                                 uint8* rgb_buf,
-                                 int width,
--                                int ystep,
--                                int uvstep);
-+                                unsigned int x_shift);
-+
-+void FastConvertYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width);
-+
-+// Can do 1x, half size or any scale down by an integer amount.
-+// Step can be negative (mirroring, rotate 180).
-+// This is the third fastest of the scalers.
-+// Only defined on Windows x86-32.
-+void ConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int step);
-+
-+// Rotate is like Convert, but applies different step to Y versus U and V.
-+// This allows rotation by 90 or 270, by stepping by stride.
-+// This is the forth fastest of the scalers.
-+// Only defined on Windows x86-32.
-+void RotateConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                    const uint8* u_buf,
-+                                    const uint8* v_buf,
-+                                    uint8* rgb_buf,
-+                                    int width,
-+                                    int ystep,
-+                                    int uvstep);
- 
- // Doubler does 4 pixels at a time.  Each pixel is replicated.
- // This is the fastest of the scalers.
--void DoubleYUVToRGB32Row(const uint8* y_buf,
--                         const uint8* u_buf,
--                         const uint8* v_buf,
--                         uint8* rgb_buf,
--                         int width);
-+// Only defined on Windows x86-32.
-+void DoubleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                             const uint8* u_buf,
-+                             const uint8* v_buf,
-+                             uint8* rgb_buf,
-+                             int width);
- 
- // Handles arbitrary scaling up or down.
- // Mirroring is supported, but not 90 or 270 degree rotation.
- // Chroma is under sampled every 2 pixels for performance.
- void ScaleYUVToRGB32Row(const uint8* y_buf,
-                         const uint8* u_buf,
-                         const uint8* v_buf,
-                         uint8* rgb_buf,
-                         int width,
-                         int source_dx);
- 
-+void ScaleYUVToRGB32Row(const uint8* y_buf,
-+                        const uint8* u_buf,
-+                        const uint8* v_buf,
-+                        uint8* rgb_buf,
-+                        int width,
-+                        int source_dx);
-+
-+void ScaleYUVToRGB32Row_C(const uint8* y_buf,
-+                          const uint8* u_buf,
-+                          const uint8* v_buf,
-+                          uint8* rgb_buf,
-+                          int width,
-+                          int source_dx);
-+
- // Handles arbitrary scaling up or down with bilinear filtering.
- // Mirroring is supported, but not 90 or 270 degree rotation.
- // Chroma is under sampled every 2 pixels for performance.
- // This is the slowest of the scalers.
- void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width,
-                               int source_dx);
- 
-+void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int source_dx);
-+
-+void LinearScaleYUVToRGB32Row_C(const uint8* y_buf,
-+                                const uint8* u_buf,
-+                                const uint8* v_buf,
-+                                uint8* rgb_buf,
-+                                int width,
-+                                int source_dx);
-+
-+
- #if defined(_MSC_VER)
- #define SIMD_ALIGNED(var) __declspec(align(16)) var
- #else
- #define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
- #endif
- extern SIMD_ALIGNED(int16 kCoefficientsRgbY[768][4]);
- 
--// Method to force C version.
--//#define USE_MMX 0
--//#define USE_SSE2 0
--
--#if !defined(USE_MMX)
--// Windows, Mac and Linux/BSD use MMX
--#if defined(__MMX__) || defined(_MSC_VER)
--#define USE_MMX 1
--#else
--#define USE_MMX 0
--#endif
--#endif
--
--#if !defined(USE_SSE2)
--#if defined(__SSE2__) || defined(ARCH_CPU_X86_64) || _M_IX86_FP==2
--#define USE_SSE2 1
--#else
--#define USE_SSE2 0
--#endif
--#endif
--
- // x64 uses MMX2 (SSE) so emms is not required.
- // Warning C4799: function has no EMMS instruction.
- // EMMS() is slow and should be called by the calling function once per image.
--#if USE_MMX && !defined(ARCH_CPU_X86_64)
-+#if defined(ARCH_CPU_X86) && !defined(ARCH_CPU_X86_64)
- #if defined(_MSC_VER)
- #define EMMS() __asm emms
- #pragma warning(disable: 4799)
- #else
- #define EMMS() asm("emms")
- #endif
- #else
- #define EMMS()
-diff --git a/gfx/ycbcr/yuv_row_c.cpp b/gfx/ycbcr/yuv_row_c.cpp
---- a/gfx/ycbcr/yuv_row_c.cpp
-+++ b/gfx/ycbcr/yuv_row_c.cpp
-@@ -1,812 +1,18 @@
- // Copyright (c) 2010 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
--#include "media/base/yuv_row.h"
--
--#ifdef _DEBUG
--#include "base/logging.h"
--#else
-+#include "yuv_row.h"
-+
- #define DCHECK(a)
--#endif
- 
- extern "C" {
- 
--#if USE_SSE2 && defined(ARCH_CPU_X86_64)
--
--// AMD64 ABI uses register paremters.
--void FastConvertYUVToRGB32Row(const uint8* y_buf,  // rdi
--                              const uint8* u_buf,  // rsi
--                              const uint8* v_buf,  // rdx
--                              uint8* rgb_buf,      // rcx
--                              int width) {         // r8
--  asm(
--  "jmp    convertend\n"
--"convertloop:"
--  "movzb  (%1),%%r10\n"
--  "add    $0x1,%1\n"
--  "movzb  (%2),%%r11\n"
--  "add    $0x1,%2\n"
--  "movq   2048(%5,%%r10,8),%%xmm0\n"
--  "movzb  (%0),%%r10\n"
--  "movq   4096(%5,%%r11,8),%%xmm1\n"
--  "movzb  0x1(%0),%%r11\n"
--  "paddsw %%xmm1,%%xmm0\n"
--  "movq   (%5,%%r10,8),%%xmm2\n"
--  "add    $0x2,%0\n"
--  "movq   (%5,%%r11,8),%%xmm3\n"
--  "paddsw %%xmm0,%%xmm2\n"
--  "paddsw %%xmm0,%%xmm3\n"
--  "shufps $0x44,%%xmm3,%%xmm2\n"
--  "psraw  $0x6,%%xmm2\n"
--  "packuswb %%xmm2,%%xmm2\n"
--  "movq   %%xmm2,0x0(%3)\n"
--  "add    $0x8,%3\n"
--"convertend:"
--  "sub    $0x2,%4\n"
--  "jns    convertloop\n"
--
--"convertnext:"
--  "add    $0x1,%4\n"
--  "js     convertdone\n"
--
--  "movzb  (%1),%%r10\n"
--  "movq   2048(%5,%%r10,8),%%xmm0\n"
--  "movzb  (%2),%%r10\n"
--  "movq   4096(%5,%%r10,8),%%xmm1\n"
--  "paddsw %%xmm1,%%xmm0\n"
--  "movzb  (%0),%%r10\n"
--  "movq   (%5,%%r10,8),%%xmm1\n"
--  "paddsw %%xmm0,%%xmm1\n"
--  "psraw  $0x6,%%xmm1\n"
--  "packuswb %%xmm1,%%xmm1\n"
--  "movd   %%xmm1,0x0(%3)\n"
--"convertdone:"
--  :
--  : "r"(y_buf),  // %0
--    "r"(u_buf),  // %1
--    "r"(v_buf),  // %2
--    "r"(rgb_buf),  // %3
--    "r"(width),  // %4
--    "r" (kCoefficientsRgbY)  // %5
--  : "memory", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3"
--);
--}
--
--void ScaleYUVToRGB32Row(const uint8* y_buf,  // rdi
--                        const uint8* u_buf,  // rsi
--                        const uint8* v_buf,  // rdx
--                        uint8* rgb_buf,      // rcx
--                        int width,           // r8
--                        int source_dx) {     // r9
--  asm(
--  "xor    %%r11,%%r11\n"
--  "sub    $0x2,%4\n"
--  "js     scalenext\n"
--
--"scaleloop:"
--  "mov    %%r11,%%r10\n"
--  "sar    $0x11,%%r10\n"
--  "movzb  (%1,%%r10,1),%%rax\n"
--  "movq   2048(%5,%%rax,8),%%xmm0\n"
--  "movzb  (%2,%%r10,1),%%rax\n"
--  "movq   4096(%5,%%rax,8),%%xmm1\n"
--  "lea    (%%r11,%6),%%r10\n"
--  "sar    $0x10,%%r11\n"
--  "movzb  (%0,%%r11,1),%%rax\n"
--  "paddsw %%xmm1,%%xmm0\n"
--  "movq   (%5,%%rax,8),%%xmm1\n"
--  "lea    (%%r10,%6),%%r11\n"
--  "sar    $0x10,%%r10\n"
--  "movzb  (%0,%%r10,1),%%rax\n"
--  "movq   (%5,%%rax,8),%%xmm2\n"
--  "paddsw %%xmm0,%%xmm1\n"
--  "paddsw %%xmm0,%%xmm2\n"
--  "shufps $0x44,%%xmm2,%%xmm1\n"
--  "psraw  $0x6,%%xmm1\n"
--  "packuswb %%xmm1,%%xmm1\n"
--  "movq   %%xmm1,0x0(%3)\n"
--  "add    $0x8,%3\n"
--  "sub    $0x2,%4\n"
--  "jns    scaleloop\n"
--
--"scalenext:"
--  "add    $0x1,%4\n"
--  "js     scaledone\n"
--
--  "mov    %%r11,%%r10\n"
--  "sar    $0x11,%%r10\n"
--  "movzb  (%1,%%r10,1),%%rax\n"
--  "movq   2048(%5,%%rax,8),%%xmm0\n"
--  "movzb  (%2,%%r10,1),%%rax\n"
--  "movq   4096(%5,%%rax,8),%%xmm1\n"
--  "paddsw %%xmm1,%%xmm0\n"
--  "sar    $0x10,%%r11\n"
--  "movzb  (%0,%%r11,1),%%rax\n"
--  "movq   (%5,%%rax,8),%%xmm1\n"
--  "paddsw %%xmm0,%%xmm1\n"
--  "psraw  $0x6,%%xmm1\n"
--  "packuswb %%xmm1,%%xmm1\n"
--  "movd   %%xmm1,0x0(%3)\n"
--
--"scaledone:"
--  :
--  : "r"(y_buf),  // %0
--    "r"(u_buf),  // %1
--    "r"(v_buf),  // %2
--    "r"(rgb_buf),  // %3
--    "r"(width),  // %4
--    "r" (kCoefficientsRgbY),  // %5
--    "r"(static_cast<long>(source_dx))  // %6
--  : "memory", "r10", "r11", "rax", "xmm0", "xmm1", "xmm2"
--);
--}
--
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width,
--                              int source_dx) {
--  asm(
--  "xor    %%r11,%%r11\n"   // x = 0
--  "sub    $0x2,%4\n"
--  "js     .lscalenext\n"
--  "cmp    $0x20000,%6\n"   // if source_dx >= 2.0
--  "jl     .lscalehalf\n"
--  "mov    $0x8000,%%r11\n" // x = 0.5 for 1/2 or less
--".lscalehalf:"
--
--".lscaleloop:"
--  "mov    %%r11,%%r10\n"
--  "sar    $0x11,%%r10\n"
--
--  "movzb  (%1, %%r10, 1), %%r13 \n"
--  "movzb  1(%1, %%r10, 1), %%r14 \n"
--  "mov    %%r11, %%rax \n"
--  "and    $0x1fffe, %%rax \n"
--  "imul   %%rax, %%r14 \n"
--  "xor    $0x1fffe, %%rax \n"
--  "imul   %%rax, %%r13 \n"
--  "add    %%r14, %%r13 \n"
--  "shr    $17, %%r13 \n"
--  "movq   2048(%5,%%r13,8), %%xmm0\n"
--
--  "movzb  (%2, %%r10, 1), %%r13 \n"
--  "movzb  1(%2, %%r10, 1), %%r14 \n"
--  "mov    %%r11, %%rax \n"
--  "and    $0x1fffe, %%rax \n"
--  "imul   %%rax, %%r14 \n"
--  "xor    $0x1fffe, %%rax \n"
--  "imul   %%rax, %%r13 \n"
--  "add    %%r14, %%r13 \n"
--  "shr    $17, %%r13 \n"
--  "movq   4096(%5,%%r13,8), %%xmm1\n"
--
--  "mov    %%r11, %%rax \n"
--  "lea    (%%r11,%6),%%r10\n"
--  "sar    $0x10,%%r11\n"
--  "paddsw %%xmm1,%%xmm0\n"
--
--  "movzb  (%0, %%r11, 1), %%r13 \n"
--  "movzb  1(%0, %%r11, 1), %%r14 \n"
--  "and    $0xffff, %%rax \n"
--  "imul   %%rax, %%r14 \n"
--  "xor    $0xffff, %%rax \n"
--  "imul   %%rax, %%r13 \n"
--  "add    %%r14, %%r13 \n"
--  "shr    $16, %%r13 \n"
--  "movq   (%5,%%r13,8),%%xmm1\n"
--
--  "mov    %%r10, %%rax \n"
--  "lea    (%%r10,%6),%%r11\n"
--  "sar    $0x10,%%r10\n"
--
--  "movzb  (%0,%%r10,1), %%r13 \n"
--  "movzb  1(%0,%%r10,1), %%r14 \n"
--  "and    $0xffff, %%rax \n"
--  "imul   %%rax, %%r14 \n"
--  "xor    $0xffff, %%rax \n"
--  "imul   %%rax, %%r13 \n"
--  "add    %%r14, %%r13 \n"
--  "shr    $16, %%r13 \n"
--  "movq   (%5,%%r13,8),%%xmm2\n"
--
--  "paddsw %%xmm0,%%xmm1\n"
--  "paddsw %%xmm0,%%xmm2\n"
--  "shufps $0x44,%%xmm2,%%xmm1\n"
--  "psraw  $0x6,%%xmm1\n"
--  "packuswb %%xmm1,%%xmm1\n"
--  "movq   %%xmm1,0x0(%3)\n"
--  "add    $0x8,%3\n"
--  "sub    $0x2,%4\n"
--  "jns    .lscaleloop\n"
--
--".lscalenext:"
--  "add    $0x1,%4\n"
--  "js     .lscaledone\n"
--
--  "mov    %%r11,%%r10\n"
--  "sar    $0x11,%%r10\n"
--
--  "movzb  (%1,%%r10,1), %%r13 \n"
--  "movq   2048(%5,%%r13,8),%%xmm0\n"
--
--  "movzb  (%2,%%r10,1), %%r13 \n"
--  "movq   4096(%5,%%r13,8),%%xmm1\n"
--
--  "paddsw %%xmm1,%%xmm0\n"
--  "sar    $0x10,%%r11\n"
--
--  "movzb  (%0,%%r11,1), %%r13 \n"
--  "movq   (%5,%%r13,8),%%xmm1\n"
--
--  "paddsw %%xmm0,%%xmm1\n"
--  "psraw  $0x6,%%xmm1\n"
--  "packuswb %%xmm1,%%xmm1\n"
--  "movd   %%xmm1,0x0(%3)\n"
--
--".lscaledone:"
--  :
--  : "r"(y_buf),  // %0
--    "r"(u_buf),  // %1
--    "r"(v_buf),  // %2
--    "r"(rgb_buf),  // %3
--    "r"(width),  // %4
--    "r" (kCoefficientsRgbY),  // %5
--    "r"(static_cast<long>(source_dx))  // %6
--  : "memory", "r10", "r11", "r13", "r14", "rax", "xmm0", "xmm1", "xmm2"
--);
--}
--
--#elif USE_MMX && !defined(ARCH_CPU_X86_64) && !defined(__PIC__)
--
--// PIC version is slower because less registers are available, so
--// non-PIC is used on platforms where it is possible.
--
--void FastConvertYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width);
--  asm(
--  ".text\n"
--  ".global FastConvertYUVToRGB32Row\n"
--"FastConvertYUVToRGB32Row:\n"
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x28(%esp),%edi\n"
--  "mov    0x2c(%esp),%esi\n"
--  "mov    0x30(%esp),%ebp\n"
--  "mov    0x34(%esp),%ecx\n"
--  "jmp    convertend\n"
--
--"convertloop:"
--  "movzbl (%edi),%eax\n"
--  "add    $0x1,%edi\n"
--  "movzbl (%esi),%ebx\n"
--  "add    $0x1,%esi\n"
--  "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
--  "movzbl (%edx),%eax\n"
--  "paddsw kCoefficientsRgbY+4096(,%ebx,8),%mm0\n"
--  "movzbl 0x1(%edx),%ebx\n"
--  "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
--  "add    $0x2,%edx\n"
--  "movq   kCoefficientsRgbY(,%ebx,8),%mm2\n"
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--"convertend:"
--  "sub    $0x2,%ecx\n"
--  "jns    convertloop\n"
--
--  "and    $0x1,%ecx\n"
--  "je     convertdone\n"
--
--  "movzbl (%edi),%eax\n"
--  "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
--  "movzbl (%esi),%eax\n"
--  "paddsw kCoefficientsRgbY+4096(,%eax,8),%mm0\n"
--  "movzbl (%edx),%eax\n"
--  "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
--  "paddsw %mm0,%mm1\n"
--  "psraw  $0x6,%mm1\n"
--  "packuswb %mm1,%mm1\n"
--  "movd   %mm1,0x0(%ebp)\n"
--"convertdone:"
--  "popa\n"
--  "ret\n"
--);
--
--
--void ScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx);
--  asm(
--  ".text\n"
--  ".global ScaleYUVToRGB32Row\n"
--"ScaleYUVToRGB32Row:\n"
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x28(%esp),%edi\n"
--  "mov    0x2c(%esp),%esi\n"
--  "mov    0x30(%esp),%ebp\n"
--  "mov    0x34(%esp),%ecx\n"
--  "xor    %ebx,%ebx\n"
--  "jmp    scaleend\n"
--
--"scaleloop:"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%edi,%eax,1),%eax\n"
--  "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%esi,%eax,1),%eax\n"
--  "paddsw kCoefficientsRgbY+4096(,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   kCoefficientsRgbY(,%eax,8),%mm2\n"
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--"scaleend:"
--  "sub    $0x2,%ecx\n"
--  "jns    scaleloop\n"
--
--  "and    $0x1,%ecx\n"
--  "je     scaledone\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%edi,%eax,1),%eax\n"
--  "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%esi,%eax,1),%eax\n"
--  "paddsw kCoefficientsRgbY+4096(,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
--  "paddsw %mm0,%mm1\n"
--  "psraw  $0x6,%mm1\n"
--  "packuswb %mm1,%mm1\n"
--  "movd   %mm1,0x0(%ebp)\n"
--
--"scaledone:"
--  "popa\n"
--  "ret\n"
--);
--
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width,
--                              int source_dx);
--  asm(
--  ".text\n"
--  ".global LinearScaleYUVToRGB32Row\n"
--"LinearScaleYUVToRGB32Row:\n"
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x28(%esp),%edi\n"
--  "mov    0x30(%esp),%ebp\n"
--
--  // source_width = width * source_dx + ebx
--  "mov    0x34(%esp), %ecx\n"
--  "imull  0x38(%esp), %ecx\n"
--  "mov    %ecx, 0x34(%esp)\n"
--
--  "mov    0x38(%esp), %ecx\n"
--  "xor    %ebx,%ebx\n"     // x = 0
--  "cmp    $0x20000,%ecx\n" // if source_dx >= 2.0
--  "jl     .lscaleend\n"
--  "mov    $0x8000,%ebx\n"  // x = 0.5 for 1/2 or less
--  "jmp    .lscaleend\n"
--
--".lscaleloop:"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--
--  "movzbl (%edi,%eax,1),%ecx\n"
--  "movzbl 1(%edi,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "andl   $0x1fffe, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0x1fffe, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $17, %ecx \n"
--  "movq   kCoefficientsRgbY+2048(,%ecx,8),%mm0\n"
--
--  "mov    0x2c(%esp),%esi\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--
--  "movzbl (%esi,%eax,1),%ecx\n"
--  "movzbl 1(%esi,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "andl   $0x1fffe, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0x1fffe, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $17, %ecx \n"
--  "paddsw kCoefficientsRgbY+4096(,%ecx,8),%mm0\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%ecx\n"
--  "movzbl 1(%edx,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "andl   $0xffff, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0xffff, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $16, %ecx \n"
--  "movq   kCoefficientsRgbY(,%ecx,8),%mm1\n"
--
--  "cmp    0x34(%esp), %ebx\n"
--  "jge    .lscalelastpixel\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%ecx\n"
--  "movzbl 1(%edx,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "andl   $0xffff, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0xffff, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $16, %ecx \n"
--  "movq   kCoefficientsRgbY(,%ecx,8),%mm2\n"
--
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--
--".lscaleend:"
--  "cmp    0x34(%esp), %ebx\n"
--  "jl     .lscaleloop\n"
--  "popa\n"
--  "ret\n"
--
--".lscalelastpixel:"
--  "paddsw %mm0, %mm1\n"
--  "psraw $6, %mm1\n"
--  "packuswb %mm1, %mm1\n"
--  "movd %mm1, (%ebp)\n"
--  "popa\n"
--  "ret\n"
--);
--
--#elif USE_MMX && !defined(ARCH_CPU_X86_64) && defined(__PIC__)
--
--extern void PICConvertYUVToRGB32Row(const uint8* y_buf,
--                                    const uint8* u_buf,
--                                    const uint8* v_buf,
--                                    uint8* rgb_buf,
--                                    int width,
--                                    int16 *kCoefficientsRgbY);
--  asm(
--  ".text\n"
--#if defined(OS_MACOSX)
--"_PICConvertYUVToRGB32Row:\n"
--#else
--"PICConvertYUVToRGB32Row:\n"
--#endif
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x28(%esp),%edi\n"
--  "mov    0x2c(%esp),%esi\n"
--  "mov    0x30(%esp),%ebp\n"
--  "mov    0x38(%esp),%ecx\n"
--
--  "jmp    .Lconvertend\n"
--
--".Lconvertloop:"
--  "movzbl (%edi),%eax\n"
--  "add    $0x1,%edi\n"
--  "movzbl (%esi),%ebx\n"
--  "add    $0x1,%esi\n"
--  "movq   2048(%ecx,%eax,8),%mm0\n"
--  "movzbl (%edx),%eax\n"
--  "paddsw 4096(%ecx,%ebx,8),%mm0\n"
--  "movzbl 0x1(%edx),%ebx\n"
--  "movq   0(%ecx,%eax,8),%mm1\n"
--  "add    $0x2,%edx\n"
--  "movq   0(%ecx,%ebx,8),%mm2\n"
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--".Lconvertend:"
--  "subl   $0x2,0x34(%esp)\n"
--  "jns    .Lconvertloop\n"
--
--  "andl   $0x1,0x34(%esp)\n"
--  "je     .Lconvertdone\n"
--
--  "movzbl (%edi),%eax\n"
--  "movq   2048(%ecx,%eax,8),%mm0\n"
--  "movzbl (%esi),%eax\n"
--  "paddsw 4096(%ecx,%eax,8),%mm0\n"
--  "movzbl (%edx),%eax\n"
--  "movq   0(%ecx,%eax,8),%mm1\n"
--  "paddsw %mm0,%mm1\n"
--  "psraw  $0x6,%mm1\n"
--  "packuswb %mm1,%mm1\n"
--  "movd   %mm1,0x0(%ebp)\n"
--".Lconvertdone:\n"
--  "popa\n"
--  "ret\n"
--);
--
--void FastConvertYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width) {
--  PICConvertYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width,
--                          &kCoefficientsRgbY[0][0]);
--}
--
--extern void PICScaleYUVToRGB32Row(const uint8* y_buf,
--                               const uint8* u_buf,
--                               const uint8* v_buf,
--                               uint8* rgb_buf,
--                               int width,
--                               int source_dx,
--                               int16 *kCoefficientsRgbY);
--
--  asm(
--  ".text\n"
--#if defined(OS_MACOSX)
--"_PICScaleYUVToRGB32Row:\n"
--#else
--"PICScaleYUVToRGB32Row:\n"
--#endif
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x28(%esp),%edi\n"
--  "mov    0x2c(%esp),%esi\n"
--  "mov    0x30(%esp),%ebp\n"
--  "mov    0x3c(%esp),%ecx\n"
--  "xor    %ebx,%ebx\n"
--  "jmp    Lscaleend\n"
--
--"Lscaleloop:"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%edi,%eax,1),%eax\n"
--  "movq   2048(%ecx,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%esi,%eax,1),%eax\n"
--  "paddsw 4096(%ecx,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   0(%ecx,%eax,8),%mm1\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   0(%ecx,%eax,8),%mm2\n"
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--"Lscaleend:"
--  "subl   $0x2,0x34(%esp)\n"
--  "jns    Lscaleloop\n"
--
--  "andl   $0x1,0x34(%esp)\n"
--  "je     Lscaledone\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%edi,%eax,1),%eax\n"
--  "movq   2048(%ecx,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--  "movzbl (%esi,%eax,1),%eax\n"
--  "paddsw 4096(%ecx,%eax,8),%mm0\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%eax\n"
--  "movq   0(%ecx,%eax,8),%mm1\n"
--  "paddsw %mm0,%mm1\n"
--  "psraw  $0x6,%mm1\n"
--  "packuswb %mm1,%mm1\n"
--  "movd   %mm1,0x0(%ebp)\n"
--
--"Lscaledone:"
--  "popa\n"
--  "ret\n"
--);
--
--
--void ScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx) {
--  PICScaleYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width, source_dx,
--                        &kCoefficientsRgbY[0][0]);
--}
--
--void PICLinearScaleYUVToRGB32Row(const uint8* y_buf,
--                                 const uint8* u_buf,
--                                 const uint8* v_buf,
--                                 uint8* rgb_buf,
--                                 int width,
--                                 int source_dx,
--                                 int16 *kCoefficientsRgbY);
--  asm(
--  ".text\n"
--#if defined(OS_MACOSX)
--"_PICLinearScaleYUVToRGB32Row:\n"
--#else
--"PICLinearScaleYUVToRGB32Row:\n"
--#endif
--  "pusha\n"
--  "mov    0x24(%esp),%edx\n"
--  "mov    0x30(%esp),%ebp\n"
--  "mov    0x34(%esp),%ecx\n"
--  "mov    0x3c(%esp),%edi\n"
--  "xor    %ebx,%ebx\n"
--
--  // source_width = width * source_dx + ebx
--  "mov    0x34(%esp), %ecx\n"
--  "imull  0x38(%esp), %ecx\n"
--  "mov    %ecx, 0x34(%esp)\n"
--
--  "mov    0x38(%esp), %ecx\n"
--  "xor    %ebx,%ebx\n"     // x = 0
--  "cmp    $0x20000,%ecx\n" // if source_dx >= 2.0
--  "jl     .lscaleend\n"
--  "mov    $0x8000,%ebx\n"  // x = 0.5 for 1/2 or less
--  "jmp    .lscaleend\n"
--
--".lscaleloop:"
--  "mov    0x28(%esp),%esi\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--
--  "movzbl (%esi,%eax,1),%ecx\n"
--  "movzbl 1(%esi,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "andl   $0x1fffe, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0x1fffe, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $17, %ecx \n"
--  "movq   2048(%edi,%ecx,8),%mm0\n"
--
--  "mov    0x2c(%esp),%esi\n"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
--
--  "movzbl (%esi,%eax,1),%ecx\n"
--  "movzbl 1(%esi,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "andl   $0x1fffe, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0x1fffe, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $17, %ecx \n"
--  "paddsw 4096(%edi,%ecx,8),%mm0\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%ecx\n"
--  "movzbl 1(%edx,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "andl   $0xffff, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0xffff, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $16, %ecx \n"
--  "movq   (%edi,%ecx,8),%mm1\n"
--
--  "cmp    0x34(%esp), %ebx\n"
--  "jge    .lscalelastpixel\n"
--
--  "mov    %ebx,%eax\n"
--  "sar    $0x10,%eax\n"
--  "movzbl (%edx,%eax,1),%ecx\n"
--  "movzbl 1(%edx,%eax,1),%esi\n"
--  "mov    %ebx,%eax\n"
--  "add    0x38(%esp),%ebx\n"
--  "andl   $0xffff, %eax \n"
--  "imul   %eax, %esi \n"
--  "xorl   $0xffff, %eax \n"
--  "imul   %eax, %ecx \n"
--  "addl   %esi, %ecx \n"
--  "shrl   $16, %ecx \n"
--  "movq   (%edi,%ecx,8),%mm2\n"
--
--  "paddsw %mm0,%mm1\n"
--  "paddsw %mm0,%mm2\n"
--  "psraw  $0x6,%mm1\n"
--  "psraw  $0x6,%mm2\n"
--  "packuswb %mm2,%mm1\n"
--  "movntq %mm1,0x0(%ebp)\n"
--  "add    $0x8,%ebp\n"
--
--".lscaleend:"
--  "cmp    %ebx, 0x34(%esp)\n"
--  "jg     .lscaleloop\n"
--  "popa\n"
--  "ret\n"
--
--".lscalelastpixel:"
--  "paddsw %mm0, %mm1\n"
--  "psraw $6, %mm1\n"
--  "packuswb %mm1, %mm1\n"
--  "movd %mm1, (%ebp)\n"
--  "popa\n"
--  "ret\n"
--);
--
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx) {
--  PICLinearScaleYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width, source_dx,
--                              &kCoefficientsRgbY[0][0]);
--}
--
--#else  // USE_MMX
--
- // C reference code that mimic the YUV assembly.
- #define packuswb(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x)))
- #define paddsw(x, y) (((x) + (y)) < -32768 ? -32768 : \
-     (((x) + (y)) > 32767 ? 32767 : ((x) + (y))))
- 
- static inline void YuvPixel(uint8 y,
-                             uint8 u,
-                             uint8 v,
-@@ -833,66 +39,71 @@ static inline void YuvPixel(uint8 y,
-   a >>= 6;
- 
-   *reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b)) |
-                                         (packuswb(g) << 8) |
-                                         (packuswb(r) << 16) |
-                                         (packuswb(a) << 24);
- }
- 
--void FastConvertYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width) {
-+void FastConvertYUVToRGB32Row_C(const uint8* y_buf,
-+                                const uint8* u_buf,
-+                                const uint8* v_buf,
-+                                uint8* rgb_buf,
-+                                int width,
-+                                unsigned int x_shift) {
-   for (int x = 0; x < width; x += 2) {
--    uint8 u = u_buf[x >> 1];
--    uint8 v = v_buf[x >> 1];
-+    uint8 u = u_buf[x >> x_shift];
-+    uint8 v = v_buf[x >> x_shift];
-     uint8 y0 = y_buf[x];
-     YuvPixel(y0, u, v, rgb_buf);
-     if ((x + 1) < width) {
-       uint8 y1 = y_buf[x + 1];
-+      if (x_shift == 0) {
-+        u = u_buf[x + 1];
-+        v = v_buf[x + 1];
-+      }
-       YuvPixel(y1, u, v, rgb_buf + 4);
-     }
-     rgb_buf += 8;  // Advance 2 pixels.
-   }
- }
- 
- // 16.16 fixed point is used.  A shift by 16 isolates the integer.
- // A shift by 17 is used to further subsample the chrominence channels.
- // & 0xffff isolates the fixed point fraction.  >> 2 to get the upper 2 bits,
- // for 1/65536 pixel accurate interpolation.
--void ScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx) {
-+void ScaleYUVToRGB32Row_C(const uint8* y_buf,
-+                          const uint8* u_buf,
-+                          const uint8* v_buf,
-+                          uint8* rgb_buf,
-+                          int width,
-+                          int source_dx) {
-   int x = 0;
-   for (int i = 0; i < width; i += 2) {
-     int y = y_buf[x >> 16];
-     int u = u_buf[(x >> 17)];
-     int v = v_buf[(x >> 17)];
-     YuvPixel(y, u, v, rgb_buf);
-     x += source_dx;
-     if ((i + 1) < width) {
-       y = y_buf[x >> 16];
-       YuvPixel(y, u, v, rgb_buf+4);
-       x += source_dx;
-     }
-     rgb_buf += 8;
-   }
- }
- 
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width,
--                              int source_dx) {
-+void LinearScaleYUVToRGB32Row_C(const uint8* y_buf,
-+                                const uint8* u_buf,
-+                                const uint8* v_buf,
-+                                uint8* rgb_buf,
-+                                int width,
-+                                int source_dx) {
-   int x = 0;
-   if (source_dx >= 0x20000) {
-     x = 32768;
-   }
-   for (int i = 0; i < width; i += 2) {
-     int y0 = y_buf[x >> 16];
-     int y1 = y_buf[(x >> 16) + 1];
-     int u0 = u_buf[(x >> 17)];
-@@ -913,11 +124,10 @@ void LinearScaleYUVToRGB32Row(const uint
-       y = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
-       YuvPixel(y, u, v, rgb_buf+4);
-       x += source_dx;
-     }
-     rgb_buf += 8;
-   }
- }
- 
--#endif  // USE_MMX
- }  // extern "C"
- 
-diff --git a/gfx/ycbcr/yuv_row_posix.cpp b/gfx/ycbcr/yuv_row_posix.cpp
---- a/gfx/ycbcr/yuv_row_posix.cpp
-+++ b/gfx/ycbcr/yuv_row_posix.cpp
-@@ -1,33 +1,32 @@
- // Copyright (c) 2010 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
--#include "media/base/yuv_row.h"
--
--#ifdef _DEBUG
--#include "base/logging.h"
--#else
-+#include "yuv_row.h"
-+#include "mozilla/SSE.h"
-+
- #define DCHECK(a)
--#endif
- 
- extern "C" {
- 
--#if USE_SSE2 && defined(ARCH_CPU_X86_64)
-+#if defined(ARCH_CPU_X86_64)
-+
-+// We don't need CPUID guards here, since x86-64 implies SSE2.
- 
- // AMD64 ABI uses register paremters.
- void FastConvertYUVToRGB32Row(const uint8* y_buf,  // rdi
-                               const uint8* u_buf,  // rsi
-                               const uint8* v_buf,  // rdx
-                               uint8* rgb_buf,      // rcx
-                               int width) {         // r8
-   asm(
--  "jmp    convertend\n"
--"convertloop:"
-+  "jmp    1f\n"
-+"0:"
-   "movzb  (%1),%%r10\n"
-   "add    $0x1,%1\n"
-   "movzb  (%2),%%r11\n"
-   "add    $0x1,%2\n"
-   "movq   2048(%5,%%r10,8),%%xmm0\n"
-   "movzb  (%0),%%r10\n"
-   "movq   4096(%5,%%r11,8),%%xmm1\n"
-   "movzb  0x1(%0),%%r11\n"
-@@ -37,36 +36,36 @@ void FastConvertYUVToRGB32Row(const uint
-   "movq   (%5,%%r11,8),%%xmm3\n"
-   "paddsw %%xmm0,%%xmm2\n"
-   "paddsw %%xmm0,%%xmm3\n"
-   "shufps $0x44,%%xmm3,%%xmm2\n"
-   "psraw  $0x6,%%xmm2\n"
-   "packuswb %%xmm2,%%xmm2\n"
-   "movq   %%xmm2,0x0(%3)\n"
-   "add    $0x8,%3\n"
--"convertend:"
-+"1:"
-   "sub    $0x2,%4\n"
--  "jns    convertloop\n"
--
--"convertnext:"
-+  "jns    0b\n"
-+
-+"2:"
-   "add    $0x1,%4\n"
--  "js     convertdone\n"
-+  "js     3f\n"
- 
-   "movzb  (%1),%%r10\n"
-   "movq   2048(%5,%%r10,8),%%xmm0\n"
-   "movzb  (%2),%%r10\n"
-   "movq   4096(%5,%%r10,8),%%xmm1\n"
-   "paddsw %%xmm1,%%xmm0\n"
-   "movzb  (%0),%%r10\n"
-   "movq   (%5,%%r10,8),%%xmm1\n"
-   "paddsw %%xmm0,%%xmm1\n"
-   "psraw  $0x6,%%xmm1\n"
-   "packuswb %%xmm1,%%xmm1\n"
-   "movd   %%xmm1,0x0(%3)\n"
--"convertdone:"
-+"3:"
-   :
-   : "r"(y_buf),  // %0
-     "r"(u_buf),  // %1
-     "r"(v_buf),  // %2
-     "r"(rgb_buf),  // %3
-     "r"(width),  // %4
-     "r" (kCoefficientsRgbY)  // %5
-   : "memory", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3"
-@@ -77,19 +76,19 @@ void ScaleYUVToRGB32Row(const uint8* y_b
-                         const uint8* u_buf,  // rsi
-                         const uint8* v_buf,  // rdx
-                         uint8* rgb_buf,      // rcx
-                         int width,           // r8
-                         int source_dx) {     // r9
-   asm(
-   "xor    %%r11,%%r11\n"
-   "sub    $0x2,%4\n"
--  "js     scalenext\n"
--
--"scaleloop:"
-+  "js     1f\n"
-+
-+"0:"
-   "mov    %%r11,%%r10\n"
-   "sar    $0x11,%%r10\n"
-   "movzb  (%1,%%r10,1),%%rax\n"
-   "movq   2048(%5,%%rax,8),%%xmm0\n"
-   "movzb  (%2,%%r10,1),%%rax\n"
-   "movq   4096(%5,%%rax,8),%%xmm1\n"
-   "lea    (%%r11,%6),%%r10\n"
-   "sar    $0x10,%%r11\n"
-@@ -103,38 +102,38 @@ void ScaleYUVToRGB32Row(const uint8* y_b
-   "paddsw %%xmm0,%%xmm1\n"
-   "paddsw %%xmm0,%%xmm2\n"
-   "shufps $0x44,%%xmm2,%%xmm1\n"
-   "psraw  $0x6,%%xmm1\n"
-   "packuswb %%xmm1,%%xmm1\n"
-   "movq   %%xmm1,0x0(%3)\n"
-   "add    $0x8,%3\n"
-   "sub    $0x2,%4\n"
--  "jns    scaleloop\n"
--
--"scalenext:"
-+  "jns    0b\n"
-+
-+"1:"
-   "add    $0x1,%4\n"
--  "js     scaledone\n"
-+  "js     2f\n"
- 
-   "mov    %%r11,%%r10\n"
-   "sar    $0x11,%%r10\n"
-   "movzb  (%1,%%r10,1),%%rax\n"
-   "movq   2048(%5,%%rax,8),%%xmm0\n"
-   "movzb  (%2,%%r10,1),%%rax\n"
-   "movq   4096(%5,%%rax,8),%%xmm1\n"
-   "paddsw %%xmm1,%%xmm0\n"
-   "sar    $0x10,%%r11\n"
-   "movzb  (%0,%%r11,1),%%rax\n"
-   "movq   (%5,%%rax,8),%%xmm1\n"
-   "paddsw %%xmm0,%%xmm1\n"
-   "psraw  $0x6,%%xmm1\n"
-   "packuswb %%xmm1,%%xmm1\n"
-   "movd   %%xmm1,0x0(%3)\n"
- 
--"scaledone:"
-+"2:"
-   :
-   : "r"(y_buf),  // %0
-     "r"(u_buf),  // %1
-     "r"(v_buf),  // %2
-     "r"(rgb_buf),  // %3
-     "r"(width),  // %4
-     "r" (kCoefficientsRgbY),  // %5
-     "r"(static_cast<long>(source_dx))  // %6
-@@ -146,23 +145,23 @@ void LinearScaleYUVToRGB32Row(const uint
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width,
-                               int source_dx) {
-   asm(
-   "xor    %%r11,%%r11\n"   // x = 0
-   "sub    $0x2,%4\n"
--  "js     .lscalenext\n"
-+  "js     2f\n"
-   "cmp    $0x20000,%6\n"   // if source_dx >= 2.0
--  "jl     .lscalehalf\n"
-+  "jl     0f\n"
-   "mov    $0x8000,%%r11\n" // x = 0.5 for 1/2 or less
--".lscalehalf:"
--
--".lscaleloop:"
-+"0:"
-+
-+"1:"
-   "mov    %%r11,%%r10\n"
-   "sar    $0x11,%%r10\n"
- 
-   "movzb  (%1, %%r10, 1), %%r13 \n"
-   "movzb  1(%1, %%r10, 1), %%r14 \n"
-   "mov    %%r11, %%rax \n"
-   "and    $0x1fffe, %%rax \n"
-   "imul   %%rax, %%r14 \n"
-@@ -215,21 +214,21 @@ void LinearScaleYUVToRGB32Row(const uint
-   "paddsw %%xmm0,%%xmm1\n"
-   "paddsw %%xmm0,%%xmm2\n"
-   "shufps $0x44,%%xmm2,%%xmm1\n"
-   "psraw  $0x6,%%xmm1\n"
-   "packuswb %%xmm1,%%xmm1\n"
-   "movq   %%xmm1,0x0(%3)\n"
-   "add    $0x8,%3\n"
-   "sub    $0x2,%4\n"
--  "jns    .lscaleloop\n"
--
--".lscalenext:"
-+  "jns    1b\n"
-+
-+"2:"
-   "add    $0x1,%4\n"
--  "js     .lscaledone\n"
-+  "js     3f\n"
- 
-   "mov    %%r11,%%r10\n"
-   "sar    $0x11,%%r10\n"
- 
-   "movzb  (%1,%%r10,1), %%r13 \n"
-   "movq   2048(%5,%%r13,8),%%xmm0\n"
- 
-   "movzb  (%2,%%r10,1), %%r13 \n"
-@@ -241,52 +240,52 @@ void LinearScaleYUVToRGB32Row(const uint
-   "movzb  (%0,%%r11,1), %%r13 \n"
-   "movq   (%5,%%r13,8),%%xmm1\n"
- 
-   "paddsw %%xmm0,%%xmm1\n"
-   "psraw  $0x6,%%xmm1\n"
-   "packuswb %%xmm1,%%xmm1\n"
-   "movd   %%xmm1,0x0(%3)\n"
- 
--".lscaledone:"
-+"3:"
-   :
-   : "r"(y_buf),  // %0
-     "r"(u_buf),  // %1
-     "r"(v_buf),  // %2
-     "r"(rgb_buf),  // %3
-     "r"(width),  // %4
-     "r" (kCoefficientsRgbY),  // %5
-     "r"(static_cast<long>(source_dx))  // %6
-   : "memory", "r10", "r11", "r13", "r14", "rax", "xmm0", "xmm1", "xmm2"
- );
- }
- 
--#elif USE_MMX && !defined(ARCH_CPU_X86_64) && !defined(__PIC__)
-+#elif defined(MOZILLA_MAY_SUPPORT_SSE) && defined(ARCH_CPU_X86_32) && !defined(__PIC__)
- 
- // PIC version is slower because less registers are available, so
- // non-PIC is used on platforms where it is possible.
--
--void FastConvertYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width);
-+void FastConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                  const uint8* u_buf,
-+                                  const uint8* v_buf,
-+                                  uint8* rgb_buf,
-+                                  int width);
-   asm(
-   ".text\n"
--  ".global FastConvertYUVToRGB32Row\n"
--"FastConvertYUVToRGB32Row:\n"
-+  ".global FastConvertYUVToRGB32Row_SSE\n"
-+  ".type FastConvertYUVToRGB32Row_SSE, @function\n"
-+"FastConvertYUVToRGB32Row_SSE:\n"
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x28(%esp),%edi\n"
-   "mov    0x2c(%esp),%esi\n"
-   "mov    0x30(%esp),%ebp\n"
-   "mov    0x34(%esp),%ecx\n"
--  "jmp    convertend\n"
--
--"convertloop:"
-+  "jmp    1f\n"
-+
-+"0:"
-   "movzbl (%edi),%eax\n"
-   "add    $0x1,%edi\n"
-   "movzbl (%esi),%ebx\n"
-   "add    $0x1,%esi\n"
-   "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
-   "movzbl (%edx),%eax\n"
-   "paddsw kCoefficientsRgbY+4096(,%ebx,8),%mm0\n"
-   "movzbl 0x1(%edx),%ebx\n"
-@@ -295,59 +294,77 @@ void FastConvertYUVToRGB32Row(const uint
-   "movq   kCoefficientsRgbY(,%ebx,8),%mm2\n"
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
--"convertend:"
-+"1:"
-   "sub    $0x2,%ecx\n"
--  "jns    convertloop\n"
-+  "jns    0b\n"
- 
-   "and    $0x1,%ecx\n"
--  "je     convertdone\n"
-+  "je     2f\n"
- 
-   "movzbl (%edi),%eax\n"
-   "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
-   "movzbl (%esi),%eax\n"
-   "paddsw kCoefficientsRgbY+4096(,%eax,8),%mm0\n"
-   "movzbl (%edx),%eax\n"
-   "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
-   "paddsw %mm0,%mm1\n"
-   "psraw  $0x6,%mm1\n"
-   "packuswb %mm1,%mm1\n"
-   "movd   %mm1,0x0(%ebp)\n"
--"convertdone:"
-+"2:"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
--
--void ScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx);
-+void FastConvertYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width)
-+{
-+  if (mozilla::supports_sse()) {
-+    FastConvertYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width);
-+    return;
-+  }
-+
-+  FastConvertYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, 1);
-+}
-+
-+
-+void ScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                            const uint8* u_buf,
-+                            const uint8* v_buf,
-+                            uint8* rgb_buf,
-+                            int width,
-+                            int source_dx);
-   asm(
-   ".text\n"
--  ".global ScaleYUVToRGB32Row\n"
--"ScaleYUVToRGB32Row:\n"
-+  ".global ScaleYUVToRGB32Row_SSE\n"
-+  ".type ScaleYUVToRGB32Row_SSE, @function\n"
-+"ScaleYUVToRGB32Row_SSE:\n"
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x28(%esp),%edi\n"
-   "mov    0x2c(%esp),%esi\n"
-   "mov    0x30(%esp),%ebp\n"
-   "mov    0x34(%esp),%ecx\n"
-   "xor    %ebx,%ebx\n"
--  "jmp    scaleend\n"
--
--"scaleloop:"
-+  "jmp    1f\n"
-+
-+"0:"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%edi,%eax,1),%eax\n"
-   "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%esi,%eax,1),%eax\n"
-   "paddsw kCoefficientsRgbY+4096(,%eax,8),%mm0\n"
-@@ -363,22 +380,22 @@ void ScaleYUVToRGB32Row(const uint8* y_b
-   "movq   kCoefficientsRgbY(,%eax,8),%mm2\n"
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
--"scaleend:"
-+"1:"
-   "sub    $0x2,%ecx\n"
--  "jns    scaleloop\n"
-+  "jns    0b\n"
- 
-   "and    $0x1,%ecx\n"
--  "je     scaledone\n"
-+  "je     2f\n"
- 
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%edi,%eax,1),%eax\n"
-   "movq   kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%esi,%eax,1),%eax\n"
-@@ -387,51 +404,71 @@ void ScaleYUVToRGB32Row(const uint8* y_b
-   "sar    $0x10,%eax\n"
-   "movzbl (%edx,%eax,1),%eax\n"
-   "movq   kCoefficientsRgbY(,%eax,8),%mm1\n"
-   "paddsw %mm0,%mm1\n"
-   "psraw  $0x6,%mm1\n"
-   "packuswb %mm1,%mm1\n"
-   "movd   %mm1,0x0(%ebp)\n"
- 
--"scaledone:"
-+"2:"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width,
--                              int source_dx);
-+void ScaleYUVToRGB32Row(const uint8* y_buf,
-+                        const uint8* u_buf,
-+                        const uint8* v_buf,
-+                        uint8* rgb_buf,
-+                        int width,
-+                        int source_dx)
-+{
-+  if (mozilla::supports_sse()) {
-+    ScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf,
-+                           width, source_dx);
-+  }
-+
-+  ScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf,
-+                       width, source_dx);
-+}
-+
-+void LinearScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                  const uint8* u_buf,
-+                                  const uint8* v_buf,
-+                                  uint8* rgb_buf,
-+                                  int width,
-+                                  int source_dx);
-   asm(
-   ".text\n"
--  ".global LinearScaleYUVToRGB32Row\n"
--"LinearScaleYUVToRGB32Row:\n"
-+  ".global LinearScaleYUVToRGB32Row_SSE\n"
-+  ".type LinearScaleYUVToRGB32Row_SSE, @function\n"
-+"LinearScaleYUVToRGB32Row_SSE:\n"
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x28(%esp),%edi\n"
-   "mov    0x30(%esp),%ebp\n"
- 
-   // source_width = width * source_dx + ebx
-   "mov    0x34(%esp), %ecx\n"
-   "imull  0x38(%esp), %ecx\n"
-   "mov    %ecx, 0x34(%esp)\n"
- 
-   "mov    0x38(%esp), %ecx\n"
-   "xor    %ebx,%ebx\n"     // x = 0
-   "cmp    $0x20000,%ecx\n" // if source_dx >= 2.0
--  "jl     .lscaleend\n"
-+  "jl     1f\n"
-   "mov    $0x8000,%ebx\n"  // x = 0.5 for 1/2 or less
--  "jmp    .lscaleend\n"
--
--".lscaleloop:"
--  "mov    %ebx,%eax\n"
--  "sar    $0x11,%eax\n"
-+  "jmp    1f\n"
-+
-+"0:"
-+  "mov    %ebx,%eax\n"
-+  "sar    $0x11,%eax\n"
- 
-   "movzbl (%edi,%eax,1),%ecx\n"
-   "movzbl 1(%edi,%eax,1),%esi\n"
-   "mov    %ebx,%eax\n"
-   "andl   $0x1fffe, %eax \n"
-   "imul   %eax, %esi \n"
-   "xorl   $0x1fffe, %eax \n"
-   "imul   %eax, %ecx \n"
-@@ -464,17 +501,17 @@ void LinearScaleYUVToRGB32Row(const uint
-   "imul   %eax, %esi \n"
-   "xorl   $0xffff, %eax \n"
-   "imul   %eax, %ecx \n"
-   "addl   %esi, %ecx \n"
-   "shrl   $16, %ecx \n"
-   "movq   kCoefficientsRgbY(,%ecx,8),%mm1\n"
- 
-   "cmp    0x34(%esp), %ebx\n"
--  "jge    .lscalelastpixel\n"
-+  "jge    2f\n"
- 
-   "mov    %ebx,%eax\n"
-   "sar    $0x10,%eax\n"
-   "movzbl (%edx,%eax,1),%ecx\n"
-   "movzbl 1(%edx,%eax,1),%esi\n"
-   "mov    %ebx,%eax\n"
-   "add    0x38(%esp),%ebx\n"
-   "andl   $0xffff, %eax \n"
-@@ -488,56 +525,76 @@ void LinearScaleYUVToRGB32Row(const uint
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
- 
--".lscaleend:"
-+"1:"
-   "cmp    0x34(%esp), %ebx\n"
--  "jl     .lscaleloop\n"
-+  "jl     0b\n"
-   "popa\n"
-   "ret\n"
- 
--".lscalelastpixel:"
-+"2:"
-   "paddsw %mm0, %mm1\n"
-   "psraw $6, %mm1\n"
-   "packuswb %mm1, %mm1\n"
-   "movd %mm1, (%ebp)\n"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
--#elif USE_MMX && !defined(ARCH_CPU_X86_64) && defined(__PIC__)
--
--extern void PICConvertYUVToRGB32Row(const uint8* y_buf,
--                                    const uint8* u_buf,
--                                    const uint8* v_buf,
--                                    uint8* rgb_buf,
--                                    int width,
--                                    int16 *kCoefficientsRgbY);
-+void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int source_dx)
-+{
-+  if (mozilla::supports_sse()) {
-+    LinearScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf,
-+                                 width, source_dx);
-+  }
-+
-+  LinearScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf,
-+                             width, source_dx);
-+}
-+
-+#elif defined(MOZILLA_MAY_SUPPORT_SSE) && defined(ARCH_CPU_X86_32) && defined(__PIC__)
-+
-+void PICConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                 const uint8* u_buf,
-+                                 const uint8* v_buf,
-+                                 uint8* rgb_buf,
-+                                 int width,
-+                                 int16 *kCoefficientsRgbY);
-+
-   asm(
-   ".text\n"
--#if defined(OS_MACOSX)
--"_PICConvertYUVToRGB32Row:\n"
-+#if defined(XP_MACOSX)
-+"_PICConvertYUVToRGB32Row_SSE:\n"
- #else
--"PICConvertYUVToRGB32Row:\n"
-+"PICConvertYUVToRGB32Row_SSE:\n"
- #endif
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x28(%esp),%edi\n"
-   "mov    0x2c(%esp),%esi\n"
-   "mov    0x30(%esp),%ebp\n"
-   "mov    0x38(%esp),%ecx\n"
- 
--  "jmp    .Lconvertend\n"
--
--".Lconvertloop:"
-+  "jmp    1f\n"
-+
-+"0:"
-   "movzbl (%edi),%eax\n"
-   "add    $0x1,%edi\n"
-   "movzbl (%esi),%ebx\n"
-   "add    $0x1,%esi\n"
-   "movq   2048(%ecx,%eax,8),%mm0\n"
-   "movzbl (%edx),%eax\n"
-   "paddsw 4096(%ecx,%ebx,8),%mm0\n"
-   "movzbl 0x1(%edx),%ebx\n"
-@@ -546,72 +603,81 @@ extern void PICConvertYUVToRGB32Row(cons
-   "movq   0(%ecx,%ebx,8),%mm2\n"
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
--".Lconvertend:"
-+"1:"
-   "subl   $0x2,0x34(%esp)\n"
--  "jns    .Lconvertloop\n"
-+  "jns    0b\n"
- 
-   "andl   $0x1,0x34(%esp)\n"
--  "je     .Lconvertdone\n"
-+  "je     2f\n"
- 
-   "movzbl (%edi),%eax\n"
-   "movq   2048(%ecx,%eax,8),%mm0\n"
-   "movzbl (%esi),%eax\n"
-   "paddsw 4096(%ecx,%eax,8),%mm0\n"
-   "movzbl (%edx),%eax\n"
-   "movq   0(%ecx,%eax,8),%mm1\n"
-   "paddsw %mm0,%mm1\n"
-   "psraw  $0x6,%mm1\n"
-   "packuswb %mm1,%mm1\n"
-   "movd   %mm1,0x0(%ebp)\n"
--".Lconvertdone:\n"
-+"2:"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
- void FastConvertYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
--                              int width) {
--  PICConvertYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width,
--                          &kCoefficientsRgbY[0][0]);
--}
--
--extern void PICScaleYUVToRGB32Row(const uint8* y_buf,
-+                              int width)
-+{
-+  if (mozilla::supports_sse()) {
-+    PICConvertYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width,
-+                                &kCoefficientsRgbY[0][0]);
-+    return;
-+  }
-+
-+  FastConvertYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, 1);
-+}
-+
-+void PICScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-                                const uint8* u_buf,
-                                const uint8* v_buf,
-                                uint8* rgb_buf,
-                                int width,
-                                int source_dx,
-                                int16 *kCoefficientsRgbY);
- 
-   asm(
-   ".text\n"
--#if defined(OS_MACOSX)
--"_PICScaleYUVToRGB32Row:\n"
-+#if defined(XP_MACOSX)
-+"_PICScaleYUVToRGB32Row_SSE:\n"
- #else
--"PICScaleYUVToRGB32Row:\n"
-+"PICScaleYUVToRGB32Row_SSE:\n"
- #endif
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x28(%esp),%edi\n"
-   "mov    0x2c(%esp),%esi\n"
-   "mov    0x30(%esp),%ebp\n"
-   "mov    0x3c(%esp),%ecx\n"
-   "xor    %ebx,%ebx\n"
--  "jmp    Lscaleend\n"
--
--"Lscaleloop:"
-+  "jmp    1f\n"
-+
-+"0:"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%edi,%eax,1),%eax\n"
-   "movq   2048(%ecx,%eax,8),%mm0\n"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%esi,%eax,1),%eax\n"
-   "paddsw 4096(%ecx,%eax,8),%mm0\n"
-@@ -627,22 +693,22 @@ extern void PICScaleYUVToRGB32Row(const 
-   "movq   0(%ecx,%eax,8),%mm2\n"
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
--"Lscaleend:"
-+"1:"
-   "subl   $0x2,0x34(%esp)\n"
--  "jns    Lscaleloop\n"
-+  "jns    0b\n"
- 
-   "andl   $0x1,0x34(%esp)\n"
--  "je     Lscaledone\n"
-+  "je     2f\n"
- 
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%edi,%eax,1),%eax\n"
-   "movq   2048(%ecx,%eax,8),%mm0\n"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
-   "movzbl (%esi,%eax,1),%eax\n"
-@@ -651,66 +717,75 @@ extern void PICScaleYUVToRGB32Row(const 
-   "sar    $0x10,%eax\n"
-   "movzbl (%edx,%eax,1),%eax\n"
-   "movq   0(%ecx,%eax,8),%mm1\n"
-   "paddsw %mm0,%mm1\n"
-   "psraw  $0x6,%mm1\n"
-   "packuswb %mm1,%mm1\n"
-   "movd   %mm1,0x0(%ebp)\n"
- 
--"Lscaledone:"
-+"2:"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
--
- void ScaleYUVToRGB32Row(const uint8* y_buf,
-                         const uint8* u_buf,
-                         const uint8* v_buf,
-                         uint8* rgb_buf,
-                         int width,
--                        int source_dx) {
--  PICScaleYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width, source_dx,
--                        &kCoefficientsRgbY[0][0]);
--}
--
--void PICLinearScaleYUVToRGB32Row(const uint8* y_buf,
--                                 const uint8* u_buf,
--                                 const uint8* v_buf,
--                                 uint8* rgb_buf,
--                                 int width,
--                                 int source_dx,
--                                 int16 *kCoefficientsRgbY);
-+                        int source_dx)
-+{
-+  if (mozilla::supports_sse()) {
-+    PICScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width, source_dx,
-+                              &kCoefficientsRgbY[0][0]);
-+    return;
-+  }
-+
-+  ScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
-+
-+void PICLinearScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                     const uint8* u_buf,
-+                                     const uint8* v_buf,
-+                                     uint8* rgb_buf,
-+                                     int width,
-+                                     int source_dx,
-+                                     int16 *kCoefficientsRgbY);
-+
-   asm(
-   ".text\n"
--#if defined(OS_MACOSX)
--"_PICLinearScaleYUVToRGB32Row:\n"
-+#if defined(XP_MACOSX)
-+"_PICLinearScaleYUVToRGB32Row_SSE:\n"
- #else
--"PICLinearScaleYUVToRGB32Row:\n"
-+"PICLinearScaleYUVToRGB32Row_SSE:\n"
- #endif
-   "pusha\n"
-   "mov    0x24(%esp),%edx\n"
-   "mov    0x30(%esp),%ebp\n"
-   "mov    0x34(%esp),%ecx\n"
-   "mov    0x3c(%esp),%edi\n"
-   "xor    %ebx,%ebx\n"
- 
-   // source_width = width * source_dx + ebx
-   "mov    0x34(%esp), %ecx\n"
-   "imull  0x38(%esp), %ecx\n"
-   "mov    %ecx, 0x34(%esp)\n"
- 
-   "mov    0x38(%esp), %ecx\n"
-   "xor    %ebx,%ebx\n"     // x = 0
-   "cmp    $0x20000,%ecx\n" // if source_dx >= 2.0
--  "jl     .lscaleend\n"
-+  "jl     1f\n"
-   "mov    $0x8000,%ebx\n"  // x = 0.5 for 1/2 or less
--  "jmp    .lscaleend\n"
--
--".lscaleloop:"
-+  "jmp    1f\n"
-+
-+"0:"
-   "mov    0x28(%esp),%esi\n"
-   "mov    %ebx,%eax\n"
-   "sar    $0x11,%eax\n"
- 
-   "movzbl (%esi,%eax,1),%ecx\n"
-   "movzbl 1(%esi,%eax,1),%esi\n"
-   "mov    %ebx,%eax\n"
-   "andl   $0x1fffe, %eax \n"
-@@ -746,17 +821,17 @@ void PICLinearScaleYUVToRGB32Row(const u
-   "imul   %eax, %esi \n"
-   "xorl   $0xffff, %eax \n"
-   "imul   %eax, %ecx \n"
-   "addl   %esi, %ecx \n"
-   "shrl   $16, %ecx \n"
-   "movq   (%edi,%ecx,8),%mm1\n"
- 
-   "cmp    0x34(%esp), %ebx\n"
--  "jge    .lscalelastpixel\n"
-+  "jge    2f\n"
- 
-   "mov    %ebx,%eax\n"
-   "sar    $0x10,%eax\n"
-   "movzbl (%edx,%eax,1),%ecx\n"
-   "movzbl 1(%edx,%eax,1),%esi\n"
-   "mov    %ebx,%eax\n"
-   "add    0x38(%esp),%ebx\n"
-   "andl   $0xffff, %eax \n"
-@@ -770,154 +845,71 @@ void PICLinearScaleYUVToRGB32Row(const u
-   "paddsw %mm0,%mm1\n"
-   "paddsw %mm0,%mm2\n"
-   "psraw  $0x6,%mm1\n"
-   "psraw  $0x6,%mm2\n"
-   "packuswb %mm2,%mm1\n"
-   "movntq %mm1,0x0(%ebp)\n"
-   "add    $0x8,%ebp\n"
- 
--".lscaleend:"
-+"1:"
-   "cmp    %ebx, 0x34(%esp)\n"
--  "jg     .lscaleloop\n"
-+  "jg     0b\n"
-   "popa\n"
-   "ret\n"
- 
--".lscalelastpixel:"
-+"2:"
-   "paddsw %mm0, %mm1\n"
-   "psraw $6, %mm1\n"
-   "packuswb %mm1, %mm1\n"
-   "movd %mm1, (%ebp)\n"
-   "popa\n"
-   "ret\n"
-+#if !defined(XP_MACOSX)
-+  ".previous\n"
-+#endif
- );
- 
-+
- void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx) {
--  PICLinearScaleYUVToRGB32Row(y_buf, u_buf, v_buf, rgb_buf, width, source_dx,
--                              &kCoefficientsRgbY[0][0]);
--}
--
--#else  // USE_MMX
--
--// C reference code that mimic the YUV assembly.
--#define packuswb(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x)))
--#define paddsw(x, y) (((x) + (y)) < -32768 ? -32768 : \
--    (((x) + (y)) > 32767 ? 32767 : ((x) + (y))))
--
--static inline void YuvPixel(uint8 y,
--                            uint8 u,
--                            uint8 v,
--                            uint8* rgb_buf) {
--
--  int b = kCoefficientsRgbY[256+u][0];
--  int g = kCoefficientsRgbY[256+u][1];
--  int r = kCoefficientsRgbY[256+u][2];
--  int a = kCoefficientsRgbY[256+u][3];
--
--  b = paddsw(b, kCoefficientsRgbY[512+v][0]);
--  g = paddsw(g, kCoefficientsRgbY[512+v][1]);
--  r = paddsw(r, kCoefficientsRgbY[512+v][2]);
--  a = paddsw(a, kCoefficientsRgbY[512+v][3]);
--
--  b = paddsw(b, kCoefficientsRgbY[y][0]);
--  g = paddsw(g, kCoefficientsRgbY[y][1]);
--  r = paddsw(r, kCoefficientsRgbY[y][2]);
--  a = paddsw(a, kCoefficientsRgbY[y][3]);
--
--  b >>= 6;
--  g >>= 6;
--  r >>= 6;
--  a >>= 6;
--
--  *reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b)) |
--                                        (packuswb(g) << 8) |
--                                        (packuswb(r) << 16) |
--                                        (packuswb(a) << 24);
--}
--
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int source_dx)
-+{
-+  if (mozilla::supports_sse()) {
-+    PICLinearScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width,
-+                                    source_dx, &kCoefficientsRgbY[0][0]);
-+    return;
-+  }
-+
-+  LinearScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
-+#else
- void FastConvertYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width) {
--  for (int x = 0; x < width; x += 2) {
--    uint8 u = u_buf[x >> 1];
--    uint8 v = v_buf[x >> 1];
--    uint8 y0 = y_buf[x];
--    YuvPixel(y0, u, v, rgb_buf);
--    if ((x + 1) < width) {
--      uint8 y1 = y_buf[x + 1];
--      YuvPixel(y1, u, v, rgb_buf + 4);
--    }
--    rgb_buf += 8;  // Advance 2 pixels.
--  }
--}
--
--// 16.16 fixed point is used.  A shift by 16 isolates the integer.
--// A shift by 17 is used to further subsample the chrominence channels.
--// & 0xffff isolates the fixed point fraction.  >> 2 to get the upper 2 bits,
--// for 1/65536 pixel accurate interpolation.
-+  FastConvertYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, 1);
-+}
-+
- void ScaleYUVToRGB32Row(const uint8* y_buf,
-                         const uint8* u_buf,
-                         const uint8* v_buf,
-                         uint8* rgb_buf,
-                         int width,
-                         int source_dx) {
--  int x = 0;
--  for (int i = 0; i < width; i += 2) {
--    int y = y_buf[x >> 16];
--    int u = u_buf[(x >> 17)];
--    int v = v_buf[(x >> 17)];
--    YuvPixel(y, u, v, rgb_buf);
--    x += source_dx;
--    if ((i + 1) < width) {
--      y = y_buf[x >> 16];
--      YuvPixel(y, u, v, rgb_buf+4);
--      x += source_dx;
--    }
--    rgb_buf += 8;
--  }
--}
-+  ScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
- 
- void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width,
-                               int source_dx) {
--  int x = 0;
--  if (source_dx >= 0x20000) {
--    x = 32768;
--  }
--  for (int i = 0; i < width; i += 2) {
--    int y0 = y_buf[x >> 16];
--    int y1 = y_buf[(x >> 16) + 1];
--    int u0 = u_buf[(x >> 17)];
--    int u1 = u_buf[(x >> 17) + 1];
--    int v0 = v_buf[(x >> 17)];
--    int v1 = v_buf[(x >> 17) + 1];
--    int y_frac = (x & 65535);
--    int uv_frac = ((x >> 1) & 65535);
--    int y = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
--    int u = (uv_frac * u1 + (uv_frac ^ 65535) * u0) >> 16;
--    int v = (uv_frac * v1 + (uv_frac ^ 65535) * v0) >> 16;
--    YuvPixel(y, u, v, rgb_buf);
--    x += source_dx;
--    if ((i + 1) < width) {
--      y0 = y_buf[x >> 16];
--      y1 = y_buf[(x >> 16) + 1];
--      y_frac = (x & 65535);
--      y = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
--      YuvPixel(y, u, v, rgb_buf+4);
--      x += source_dx;
--    }
--    rgb_buf += 8;
--  }
--}
--
--#endif  // USE_MMX
--}  // extern "C"
--
-+  LinearScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
-+#endif
-+
-+}
-diff --git a/gfx/ycbcr/yuv_row_table.cpp b/gfx/ycbcr/yuv_row_table.cpp
---- a/gfx/ycbcr/yuv_row_table.cpp
-+++ b/gfx/ycbcr/yuv_row_table.cpp
-@@ -1,13 +1,13 @@
- // Copyright (c) 2010 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
--#include "media/base/yuv_row.h"
-+#include "yuv_row.h"
- 
- extern "C" {
- 
- #define RGBY(i) { \
-   static_cast<int16>(1.164 * 64 * (i - 16) + 0.5), \
-   static_cast<int16>(1.164 * 64 * (i - 16) + 0.5), \
-   static_cast<int16>(1.164 * 64 * (i - 16) + 0.5), \
-   0 \
-diff --git a/gfx/ycbcr/yuv_row_win.cpp b/gfx/ycbcr/yuv_row_win.cpp
---- a/gfx/ycbcr/yuv_row_win.cpp
-+++ b/gfx/ycbcr/yuv_row_win.cpp
-@@ -1,26 +1,27 @@
- // Copyright (c) 2010 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
--#include "media/base/yuv_row.h"
-+#include "yuv_row.h"
-+#include "mozilla/SSE.h"
- 
- #define kCoefficientsRgbU kCoefficientsRgbY + 2048
- #define kCoefficientsRgbV kCoefficientsRgbY + 4096
- 
- extern "C" {
- 
--#if USE_MMX
--__declspec(naked)
--void FastConvertYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width) {
-+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
-+__declspec(naked)
-+void FastConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                  const uint8* u_buf,
-+                                  const uint8* v_buf,
-+                                  uint8* rgb_buf,
-+                                  int width) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]   // Y
-     mov       edi, [esp + 32 + 8]   // U
-     mov       esi, [esp + 32 + 12]  // V
-     mov       ebp, [esp + 32 + 16]  // rgb
-     mov       ecx, [esp + 32 + 20]  // width
-     jmp       convertend
-@@ -64,22 +65,22 @@ void FastConvertYUVToRGB32Row(const uint
-  convertdone :
- 
-     popad
-     ret
-   }
- }
- 
- __declspec(naked)
--void ConvertYUVToRGB32Row(const uint8* y_buf,
--                          const uint8* u_buf,
--                          const uint8* v_buf,
--                          uint8* rgb_buf,
--                          int width,
--                          int step) {
-+void ConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int step) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]   // Y
-     mov       edi, [esp + 32 + 8]   // U
-     mov       esi, [esp + 32 + 12]  // V
-     mov       ebp, [esp + 32 + 16]  // rgb
-     mov       ecx, [esp + 32 + 20]  // width
-     mov       ebx, [esp + 32 + 24]  // step
-@@ -125,23 +126,23 @@ void ConvertYUVToRGB32Row(const uint8* y
-  wdone :
- 
-     popad
-     ret
-   }
- }
- 
- __declspec(naked)
--void RotateConvertYUVToRGB32Row(const uint8* y_buf,
--                                const uint8* u_buf,
--                                const uint8* v_buf,
--                                uint8* rgb_buf,
--                                int width,
--                                int ystep,
--                                int uvstep) {
-+void RotateConvertYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                    const uint8* u_buf,
-+                                    const uint8* v_buf,
-+                                    uint8* rgb_buf,
-+                                    int width,
-+                                    int ystep,
-+                                    int uvstep) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]   // Y
-     mov       edi, [esp + 32 + 8]   // U
-     mov       esi, [esp + 32 + 12]  // V
-     mov       ebp, [esp + 32 + 16]  // rgb
-     mov       ecx, [esp + 32 + 20]  // width
-     jmp       wend
-@@ -188,21 +189,21 @@ void RotateConvertYUVToRGB32Row(const ui
-  wdone :
- 
-     popad
-     ret
-   }
- }
- 
- __declspec(naked)
--void DoubleYUVToRGB32Row(const uint8* y_buf,
--                         const uint8* u_buf,
--                         const uint8* v_buf,
--                         uint8* rgb_buf,
--                         int width) {
-+void DoubleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                             const uint8* u_buf,
-+                             const uint8* v_buf,
-+                             uint8* rgb_buf,
-+                             int width) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]   // Y
-     mov       edi, [esp + 32 + 8]   // U
-     mov       esi, [esp + 32 + 12]  // V
-     mov       ebp, [esp + 32 + 16]  // rgb
-     mov       ecx, [esp + 32 + 20]  // width
-     jmp       wend
-@@ -256,26 +257,26 @@ void DoubleYUVToRGB32Row(const uint8* y_
-     jns       wloop1
-  wdone :
-     popad
-     ret
-   }
- }
- 
- // This version does general purpose scaling by any amount, up or down.
--// The only thing it can not do it rotation by 90 or 270.
--// For performance the chroma is under sampled, reducing cost of a 3x
-+// The only thing it cannot do is rotation by 90 or 270.
-+// For performance the chroma is under-sampled, reducing cost of a 3x
- // 1080p scale from 8.4 ms to 5.4 ms.
- __declspec(naked)
--void ScaleYUVToRGB32Row(const uint8* y_buf,
--                        const uint8* u_buf,
--                        const uint8* v_buf,
--                        uint8* rgb_buf,
--                        int width,
--                        int source_dx) {
-+void ScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                            const uint8* u_buf,
-+                            const uint8* v_buf,
-+                            uint8* rgb_buf,
-+                            int width,
-+                            int source_dx) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]   // Y
-     mov       edi, [esp + 32 + 8]   // U
-     mov       esi, [esp + 32 + 12]  // V
-     mov       ebp, [esp + 32 + 16]  // rgb
-     mov       ecx, [esp + 32 + 20]  // width
-     xor       ebx, ebx              // x
-@@ -333,22 +334,22 @@ void ScaleYUVToRGB32Row(const uint8* y_b
- 
-  scaledone :
-     popad
-     ret
-   }
- }
- 
- __declspec(naked)
--void LinearScaleYUVToRGB32Row(const uint8* y_buf,
--                              const uint8* u_buf,
--                              const uint8* v_buf,
--                              uint8* rgb_buf,
--                              int width,
--                              int source_dx) {
-+void LinearScaleYUVToRGB32Row_SSE(const uint8* y_buf,
-+                                  const uint8* u_buf,
-+                                  const uint8* v_buf,
-+                                  uint8* rgb_buf,
-+                                  int width,
-+                                  int source_dx) {
-   __asm {
-     pushad
-     mov       edx, [esp + 32 + 4]  // Y
-     mov       edi, [esp + 32 + 8]  // U
-                 // [esp + 32 + 12] // V
-     mov       ebp, [esp + 32 + 16] // rgb
-     mov       ecx, [esp + 32 + 20] // width
-     imul      ecx, [esp + 32 + 24] // source_dx
-@@ -438,152 +439,60 @@ lscalelastpixel:
-     paddsw    mm1, mm0
-     psraw     mm1, 6
-     packuswb  mm1, mm1
-     movd      [ebp], mm1
-     popad
-     ret
-   };
- }
--#else  // USE_MMX
--
--// C reference code that mimic the YUV assembly.
--#define packuswb(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x)))
--#define paddsw(x, y) (((x) + (y)) < -32768 ? -32768 : \
--    (((x) + (y)) > 32767 ? 32767 : ((x) + (y))))
--
--static inline void YuvPixel(uint8 y,
--                            uint8 u,
--                            uint8 v,
--                            uint8* rgb_buf) {
--
--  int b = kCoefficientsRgbY[256+u][0];
--  int g = kCoefficientsRgbY[256+u][1];
--  int r = kCoefficientsRgbY[256+u][2];
--  int a = kCoefficientsRgbY[256+u][3];
--
--  b = paddsw(b, kCoefficientsRgbY[512+v][0]);
--  g = paddsw(g, kCoefficientsRgbY[512+v][1]);
--  r = paddsw(r, kCoefficientsRgbY[512+v][2]);
--  a = paddsw(a, kCoefficientsRgbY[512+v][3]);
--
--  b = paddsw(b, kCoefficientsRgbY[y][0]);
--  g = paddsw(g, kCoefficientsRgbY[y][1]);
--  r = paddsw(r, kCoefficientsRgbY[y][2]);
--  a = paddsw(a, kCoefficientsRgbY[y][3]);
--
--  b >>= 6;
--  g >>= 6;
--  r >>= 6;
--  a >>= 6;
--
--  *reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b)) |
--                                        (packuswb(g) << 8) |
--                                        (packuswb(r) << 16) |
--                                        (packuswb(a) << 24);
--}
--
--#if TEST_MMX_YUV
--static inline void YuvPixel(uint8 y,
--                            uint8 u,
--                            uint8 v,
--                            uint8* rgb_buf) {
--
--  __asm {
--    movzx     eax, u
--    movq      mm0, [kCoefficientsRgbY+2048 + 8 * eax]
--    movzx     eax, v
--    paddsw    mm0, [kCoefficientsRgbY+4096 + 8 * eax]
--    movzx     eax, y
--    movq      mm1, [kCoefficientsRgbY + 8 * eax]
--    paddsw    mm1, mm0
--    psraw     mm1, 6
--    packuswb  mm1, mm1
--    mov       eax, rgb_buf
--    movd      [eax], mm1
--    emms
--  }
--}
--#endif
-+#endif // if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
- 
- void FastConvertYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width) {
--  for (int x = 0; x < width; x += 2) {
--    uint8 u = u_buf[x >> 1];
--    uint8 v = v_buf[x >> 1];
--    uint8 y0 = y_buf[x];
--    YuvPixel(y0, u, v, rgb_buf);
--    if ((x + 1) < width) {
--      uint8 y1 = y_buf[x + 1];
--      YuvPixel(y1, u, v, rgb_buf + 4);
--    }
--    rgb_buf += 8;  // Advance 2 pixels.
--  }
--}
--
--// 16.16 fixed point is used.  A shift by 16 isolates the integer.
--// A shift by 17 is used to further subsample the chrominence channels.
--// & 0xffff isolates the fixed point fraction.  >> 2 to get the upper 2 bits,
--// for 1/65536 pixel accurate interpolation.
-+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
-+  if (mozilla::supports_sse()) {
-+    FastConvertYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width);
-+    return;
-+  }
-+#endif
-+
-+  FastConvertYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, 1);
-+}
-+
- void ScaleYUVToRGB32Row(const uint8* y_buf,
-                         const uint8* u_buf,
-                         const uint8* v_buf,
-                         uint8* rgb_buf,
-                         int width,
-                         int source_dx) {
--  int x = 0;
--  for (int i = 0; i < width; i += 2) {
--    int y = y_buf[x >> 16];
--    int u = u_buf[(x >> 17)];
--    int v = v_buf[(x >> 17)];
--    YuvPixel(y, u, v, rgb_buf);
--    x += source_dx;
--    if ((i + 1) < width) {
--      y = y_buf[x >> 16];
--      YuvPixel(y, u, v, rgb_buf+4);
--      x += source_dx;
--    }
--    rgb_buf += 8;
--  }
--}
-+
-+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
-+  if (mozilla::supports_sse()) {
-+    ScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+    return;
-+  }
-+#endif
-+
-+  ScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
- 
- void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-                               const uint8* u_buf,
-                               const uint8* v_buf,
-                               uint8* rgb_buf,
-                               int width,
-                               int source_dx) {
--  int x = 0;
--  if (source_dx >= 0x20000) {
--    x = 32768;
--  }
--  for (int i = 0; i < width; i += 2) {
--    int y0 = y_buf[x >> 16];
--    int y1 = y_buf[(x >> 16) + 1];
--    int u0 = u_buf[(x >> 17)];
--    int u1 = u_buf[(x >> 17) + 1];
--    int v0 = v_buf[(x >> 17)];
--    int v1 = v_buf[(x >> 17) + 1];
--    int y_frac = (x & 65535);
--    int uv_frac = ((x >> 1) & 65535);
--    int y = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
--    int u = (uv_frac * u1 + (uv_frac ^ 65535) * u0) >> 16;
--    int v = (uv_frac * v1 + (uv_frac ^ 65535) * v0) >> 16;
--    YuvPixel(y, u, v, rgb_buf);
--    x += source_dx;
--    if ((i + 1) < width) {
--      y0 = y_buf[x >> 16];
--      y1 = y_buf[(x >> 16) + 1];
--      y_frac = (x & 65535);
--      y = (y_frac * y1 + (y_frac ^ 65535) * y0) >> 16;
--      YuvPixel(y, u, v, rgb_buf+4);
--      x += source_dx;
--    }
--    rgb_buf += 8;
--  }
--}
--
--#endif  // USE_MMX
--}  // extern "C"
--
-+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_M_IX86)
-+  if (mozilla::supports_sse()) {
-+    LinearScaleYUVToRGB32Row_SSE(y_buf, u_buf, v_buf, rgb_buf, width,
-+                                 source_dx);
-+    return;
-+  }
-+#endif
-+
-+  LinearScaleYUVToRGB32Row_C(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
-+
-+} // extern "C"
deleted file mode 100644
--- a/gfx/ycbcr/update.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-# update.sh <chromium-src-directory>
-cp $1/media/base/yuv_convert.h .
-cp $1/media/base/yuv_convert.cc yuv_convert.cpp
-cp $1/media/base/yuv_row.h .
-cp $1/media/base/yuv_row_table.cc yuv_row_table.cpp
-cp $1/media/base/yuv_row_posix.cc yuv_row_posix.cpp
-cp $1/media/base/yuv_row_win.cc yuv_row_win.cpp
-cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp
-patch -p3 <convert.patch
-patch -p3 <win64.patch
-patch -p3 <TypeFromSize.patch
-patch -p3 <QuellGccWarnings.patch
-patch -p3 <clang-cl-workaround.patch
deleted file mode 100644
--- a/gfx/ycbcr/win64.patch
+++ /dev/null
@@ -1,210 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_row_win64.cpp b/gfx/ycbcr/yuv_row_win64.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/ycbcr/yuv_row_win64.cpp
-@@ -0,0 +1,205 @@
-+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "yuv_row.h"
-+
-+extern "C" {
-+
-+// x64 compiler doesn't support MMX and inline assembler.  Use SSE2 intrinsics.
-+
-+#define kCoefficientsRgbU (reinterpret_cast<uint8*>(kCoefficientsRgbY) + 2048)
-+#define kCoefficientsRgbV (reinterpret_cast<uint8*>(kCoefficientsRgbY) + 4096)
-+
-+#include <emmintrin.h>
-+
-+static void FastConvertYUVToRGB32Row_SSE2(const uint8* y_buf,
-+                                          const uint8* u_buf,
-+                                          const uint8* v_buf,
-+                                          uint8* rgb_buf,
-+                                          int width) {
-+  __m128i xmm0, xmmY1, xmmY2;
-+  __m128  xmmY;
-+
-+  while (width >= 2) {
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * *u_buf++)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * *v_buf++)));
-+
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * *y_buf++));
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+
-+    xmmY2 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * *y_buf++));
-+    xmmY2 = _mm_adds_epi16(xmmY2, xmm0);
-+
-+    xmmY = _mm_shuffle_ps(_mm_castsi128_ps(xmmY1), _mm_castsi128_ps(xmmY2),
-+                          0x44);
-+    xmmY1 = _mm_srai_epi16(_mm_castps_si128(xmmY), 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+
-+    _mm_storel_epi64(reinterpret_cast<__m128i*>(rgb_buf), xmmY1);
-+    rgb_buf += 8;
-+    width -= 2;
-+  }
-+
-+  if (width) {
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * *u_buf)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * *v_buf)));
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * *y_buf));
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+    xmmY1 = _mm_srai_epi16(xmmY1, 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+    *reinterpret_cast<uint32*>(rgb_buf) = _mm_cvtsi128_si32(xmmY1);
-+  }
-+}
-+
-+static void ScaleYUVToRGB32Row_SSE2(const uint8* y_buf,
-+                                    const uint8* u_buf,
-+                                    const uint8* v_buf,
-+                                    uint8* rgb_buf,
-+                                    int width,
-+                                    int source_dx) {
-+  __m128i xmm0, xmmY1, xmmY2;
-+  __m128  xmmY;
-+  uint8 u, v, y;
-+  int x = 0;
-+
-+  while (width >= 2) {
-+    u = u_buf[x >> 17];
-+    v = v_buf[x >> 17];
-+    y = y_buf[x >> 16];
-+    x += source_dx;
-+
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * u)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * v)));
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+
-+    y = y_buf[x >> 16];
-+    x += source_dx;
-+
-+    xmmY2 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+    xmmY2 = _mm_adds_epi16(xmmY2, xmm0);
-+
-+    xmmY = _mm_shuffle_ps(_mm_castsi128_ps(xmmY1), _mm_castsi128_ps(xmmY2),
-+                          0x44);
-+    xmmY1 = _mm_srai_epi16(_mm_castps_si128(xmmY), 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+
-+    _mm_storel_epi64(reinterpret_cast<__m128i*>(rgb_buf), xmmY1);
-+    rgb_buf += 8;
-+    width -= 2;
-+  }
-+
-+  if (width) {
-+    u = u_buf[x >> 17];
-+    v = v_buf[x >> 17];
-+    y = y_buf[x >> 16];
-+
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * u)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * v)));
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+    xmmY1 = _mm_srai_epi16(xmmY1, 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+    *reinterpret_cast<uint32*>(rgb_buf) = _mm_cvtsi128_si32(xmmY1);
-+  }
-+}
-+
-+static void LinearScaleYUVToRGB32Row_SSE2(const uint8* y_buf,
-+                                          const uint8* u_buf,
-+                                          const uint8* v_buf,
-+                                          uint8* rgb_buf,
-+                                          int width,
-+                                          int source_dx) {
-+  __m128i xmm0, xmmY1, xmmY2;
-+  __m128  xmmY;
-+  uint8 u0, u1, v0, v1, y0, y1;
-+  uint32 uv_frac, y_frac, u, v, y;
-+  int x = 0;
-+
-+  if (source_dx >= 0x20000) {
-+    x = 32768;
-+  }
-+
-+  while(width >= 2) {
-+    u0 = u_buf[x >> 17];
-+    u1 = u_buf[(x >> 17) + 1];
-+    v0 = v_buf[x >> 17];
-+    v1 = v_buf[(x >> 17) + 1];
-+    y0 = y_buf[x >> 16];
-+    y1 = y_buf[(x >> 16) + 1];
-+    uv_frac = (x & 0x1fffe);
-+    y_frac = (x & 0xffff);
-+    u = (uv_frac * u1 + (uv_frac ^ 0x1fffe) * u0) >> 17;
-+    v = (uv_frac * v1 + (uv_frac ^ 0x1fffe) * v0) >> 17;
-+    y = (y_frac * y1 + (y_frac ^ 0xffff) * y0) >> 16;
-+    x += source_dx;
-+
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * u)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * v)));
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+
-+    y0 = y_buf[x >> 16];
-+    y1 = y_buf[(x >> 16) + 1];
-+    y_frac = (x & 0xffff);
-+    y = (y_frac * y1 + (y_frac ^ 0xffff) * y0) >> 16;
-+    x += source_dx;
-+
-+    xmmY2 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+    xmmY2 = _mm_adds_epi16(xmmY2, xmm0);
-+
-+    xmmY = _mm_shuffle_ps(_mm_castsi128_ps(xmmY1), _mm_castsi128_ps(xmmY2),
-+                          0x44);
-+    xmmY1 = _mm_srai_epi16(_mm_castps_si128(xmmY), 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+
-+    _mm_storel_epi64(reinterpret_cast<__m128i*>(rgb_buf), xmmY1);
-+    rgb_buf += 8;
-+    width -= 2;
-+  }
-+
-+  if (width) {
-+    u = u_buf[x >> 17];
-+    v = v_buf[x >> 17];
-+    y = y_buf[x >> 16];
-+
-+    xmm0 = _mm_adds_epi16(_mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbU + 8 * u)),
-+                          _mm_loadl_epi64(reinterpret_cast<__m128i*>(kCoefficientsRgbV + 8 * v)));
-+    xmmY1 = _mm_loadl_epi64(reinterpret_cast<__m128i*>(reinterpret_cast<uint8*>(kCoefficientsRgbY) + 8 * y));
-+
-+    xmmY1 = _mm_adds_epi16(xmmY1, xmm0);
-+    xmmY1 = _mm_srai_epi16(xmmY1, 6);
-+    xmmY1 = _mm_packus_epi16(xmmY1, xmmY1);
-+    *reinterpret_cast<uint32*>(rgb_buf) = _mm_cvtsi128_si32(xmmY1);
-+  }
-+}
-+
-+void FastConvertYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width) {
-+  FastConvertYUVToRGB32Row_SSE2(y_buf, u_buf, v_buf, rgb_buf, width);
-+}
-+
-+void ScaleYUVToRGB32Row(const uint8* y_buf,
-+                        const uint8* u_buf,
-+                        const uint8* v_buf,
-+                        uint8* rgb_buf,
-+                        int width,
-+                        int source_dx) {
-+  ScaleYUVToRGB32Row_SSE2(y_buf, u_buf, v_buf, rgb_buf, width, source_dx);
-+}
-+
-+void LinearScaleYUVToRGB32Row(const uint8* y_buf,
-+                              const uint8* u_buf,
-+                              const uint8* v_buf,
-+                              uint8* rgb_buf,
-+                              int width,
-+                              int source_dx) {
-+  LinearScaleYUVToRGB32Row_SSE2(y_buf, u_buf, v_buf, rgb_buf, width,
-+                                source_dx);
-+}
-+
-+} // extern "C"
--- a/gfx/ycbcr/yuv_row_posix.cpp
+++ b/gfx/ycbcr/yuv_row_posix.cpp
@@ -14,252 +14,249 @@ extern "C" {
 // We don't need CPUID guards here, since x86-64 implies SSE2.
 
 // AMD64 ABI uses register paremters.
 void FastConvertYUVToRGB32Row(const uint8* y_buf,  // rdi
                               const uint8* u_buf,  // rsi
                               const uint8* v_buf,  // rdx
                               uint8* rgb_buf,      // rcx
                               int width) {         // r8
-  asm(
+  asm volatile(
   "jmp    1f\n"
 "0:"
-  "movzb  (%1),%%r10\n"
-  "add    $0x1,%1\n"
-  "movzb  (%2),%%r11\n"
-  "add    $0x1,%2\n"
-  "movq   2048(%5,%%r10,8),%%xmm0\n"
-  "movzb  (%0),%%r10\n"
-  "movq   4096(%5,%%r11,8),%%xmm1\n"
-  "movzb  0x1(%0),%%r11\n"
+  "movzb  (%[u_buf]),%%r10\n"
+  "add    $0x1,%[u_buf]\n"
+  "movzb  (%[v_buf]),%%r11\n"
+  "add    $0x1,%[v_buf]\n"
+  "movq   2048(%[kCoefficientsRgbY],%%r10,8),%%xmm0\n"
+  "movzb  (%[y_buf]),%%r10\n"
+  "movq   4096(%[kCoefficientsRgbY],%%r11,8),%%xmm1\n"
+  "movzb  0x1(%[y_buf]),%%r11\n"
   "paddsw %%xmm1,%%xmm0\n"
-  "movq   (%5,%%r10,8),%%xmm2\n"
-  "add    $0x2,%0\n"
-  "movq   (%5,%%r11,8),%%xmm3\n"
+  "movq   (%[kCoefficientsRgbY],%%r10,8),%%xmm2\n"
+  "add    $0x2,%[y_buf]\n"
+  "movq   (%[kCoefficientsRgbY],%%r11,8),%%xmm3\n"
   "paddsw %%xmm0,%%xmm2\n"
   "paddsw %%xmm0,%%xmm3\n"
   "shufps $0x44,%%xmm3,%%xmm2\n"
   "psraw  $0x6,%%xmm2\n"
   "packuswb %%xmm2,%%xmm2\n"
-  "movq   %%xmm2,0x0(%3)\n"
-  "add    $0x8,%3\n"
+  "movq   %%xmm2,0x0(%[rgb_buf])\n"
+  "add    $0x8,%[rgb_buf]\n"
 "1:"
-  "sub    $0x2,%4\n"
+  "sub    $0x2,%[width]\n"
   "jns    0b\n"
 
 "2:"
-  "add    $0x1,%4\n"
+  "add    $0x1,%[width]\n"
   "js     3f\n"
 
-  "movzb  (%1),%%r10\n"
-  "movq   2048(%5,%%r10,8),%%xmm0\n"
-  "movzb  (%2),%%r10\n"
-  "movq   4096(%5,%%r10,8),%%xmm1\n"
+  "movzb  (%[u_buf]),%%r10\n"
+  "movq   2048(%[kCoefficientsRgbY],%%r10,8),%%xmm0\n"
+  "movzb  (%[v_buf]),%%r10\n"
+  "movq   4096(%[kCoefficientsRgbY],%%r10,8),%%xmm1\n"
   "paddsw %%xmm1,%%xmm0\n"
-  "movzb  (%0),%%r10\n"
-  "movq   (%5,%%r10,8),%%xmm1\n"
+  "movzb  (%[y_buf]),%%r10\n"
+  "movq   (%[kCoefficientsRgbY],%%r10,8),%%xmm1\n"
   "paddsw %%xmm0,%%xmm1\n"
   "psraw  $0x6,%%xmm1\n"
   "packuswb %%xmm1,%%xmm1\n"
-  "movd   %%xmm1,0x0(%3)\n"
+  "movd   %%xmm1,0x0(%[rgb_buf])\n"
 "3:"
-  :
-  : "r"(y_buf),  // %0
-    "r"(u_buf),  // %1
-    "r"(v_buf),  // %2
-    "r"(rgb_buf),  // %3
-    "r"(width),  // %4
-    "r" (kCoefficientsRgbY)  // %5
-  : "memory", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3"
+  : [y_buf] "+r"(y_buf),
+    [u_buf] "+r"(u_buf),
+    [v_buf] "+r"(v_buf),
+    [rgb_buf] "+r"(rgb_buf),
+    [width] "+r"(width)
+  : [kCoefficientsRgbY] "r" (kCoefficientsRgbY)
+  : "cc", "memory", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3"
 );
 }
 
 void ScaleYUVToRGB32Row(const uint8* y_buf,  // rdi
                         const uint8* u_buf,  // rsi
                         const uint8* v_buf,  // rdx
                         uint8* rgb_buf,      // rcx
                         int width,           // r8
                         int source_dx) {     // r9
-  asm(
+  asm volatile(
   "xor    %%r11,%%r11\n"
-  "sub    $0x2,%4\n"
+  "sub    $0x2,%[width]\n"
   "js     1f\n"
 
 "0:"
   "mov    %%r11,%%r10\n"
   "sar    $0x11,%%r10\n"
-  "movzb  (%1,%%r10,1),%%rax\n"
-  "movq   2048(%5,%%rax,8),%%xmm0\n"
-  "movzb  (%2,%%r10,1),%%rax\n"
-  "movq   4096(%5,%%rax,8),%%xmm1\n"
-  "lea    (%%r11,%6),%%r10\n"
+  "movzb  (%[u_buf],%%r10,1),%%rax\n"
+  "movq   2048(%[kCoefficientsRgbY],%%rax,8),%%xmm0\n"
+  "movzb  (%[v_buf],%%r10,1),%%rax\n"
+  "movq   4096(%[kCoefficientsRgbY],%%rax,8),%%xmm1\n"
+  "lea    (%%r11,%[source_dx]),%%r10\n"
   "sar    $0x10,%%r11\n"
-  "movzb  (%0,%%r11,1),%%rax\n"
+  "movzb  (%[y_buf],%%r11,1),%%rax\n"
   "paddsw %%xmm1,%%xmm0\n"
-  "movq   (%5,%%rax,8),%%xmm1\n"
-  "lea    (%%r10,%6),%%r11\n"
+  "movq   (%[kCoefficientsRgbY],%%rax,8),%%xmm1\n"
+  "lea    (%%r10,%[source_dx]),%%r11\n"
   "sar    $0x10,%%r10\n"
-  "movzb  (%0,%%r10,1),%%rax\n"
-  "movq   (%5,%%rax,8),%%xmm2\n"
+  "movzb  (%[y_buf],%%r10,1),%%rax\n"
+  "movq   (%[kCoefficientsRgbY],%%rax,8),%%xmm2\n"
   "paddsw %%xmm0,%%xmm1\n"
   "paddsw %%xmm0,%%xmm2\n"
   "shufps $0x44,%%xmm2,%%xmm1\n"
   "psraw  $0x6,%%xmm1\n"
   "packuswb %%xmm1,%%xmm1\n"
-  "movq   %%xmm1,0x0(%3)\n"
-  "add    $0x8,%3\n"
-  "sub    $0x2,%4\n"
+  "movq   %%xmm1,0x0(%[rgb_buf])\n"
+  "add    $0x8,%[rgb_buf]\n"
+  "sub    $0x2,%[width]\n"
   "jns    0b\n"
 
 "1:"
-  "add    $0x1,%4\n"
+  "add    $0x1,%[width]\n"
   "js     2f\n"
 
   "mov    %%r11,%%r10\n"
   "sar    $0x11,%%r10\n"
-  "movzb  (%1,%%r10,1),%%rax\n"
-  "movq   2048(%5,%%rax,8),%%xmm0\n"
-  "movzb  (%2,%%r10,1),%%rax\n"
-  "movq   4096(%5,%%rax,8),%%xmm1\n"
+  "movzb  (%[u_buf],%%r10,1),%%rax\n"
+  "movq   2048(%[kCoefficientsRgbY],%%rax,8),%%xmm0\n"
+  "movzb  (%[v_buf],%%r10,1),%%rax\n"
+  "movq   4096(%[kCoefficientsRgbY],%%rax,8),%%xmm1\n"
   "paddsw %%xmm1,%%xmm0\n"
   "sar    $0x10,%%r11\n"
-  "movzb  (%0,%%r11,1),%%rax\n"
-  "movq   (%5,%%rax,8),%%xmm1\n"
+  "movzb  (%[y_buf],%%r11,1),%%rax\n"
+  "movq   (%[kCoefficientsRgbY],%%rax,8),%%xmm1\n"
   "paddsw %%xmm0,%%xmm1\n"
   "psraw  $0x6,%%xmm1\n"
   "packuswb %%xmm1,%%xmm1\n"
-  "movd   %%xmm1,0x0(%3)\n"
+  "movd   %%xmm1,0x0(%[rgb_buf])\n"
 
 "2:"
-  :
-  : "r"(y_buf),  // %0
-    "r"(u_buf),  // %1
-    "r"(v_buf),  // %2
-    "r"(rgb_buf),  // %3
-    "r"(width),  // %4
-    "r" (kCoefficientsRgbY),  // %5
-    "r"(static_cast<long>(source_dx))  // %6
-  : "memory", "r10", "r11", "rax", "xmm0", "xmm1", "xmm2"
+  : [rgb_buf] "+r"(rgb_buf),
+    [width] "+r"(width)
+  : [y_buf] "r"(y_buf),
+    [u_buf] "r"(u_buf),
+    [v_buf] "r"(v_buf),
+    [kCoefficientsRgbY] "r" (kCoefficientsRgbY),
+    [source_dx] "r"(static_cast<long>(source_dx))
+  : "cc", "memory", "r10", "r11", "rax", "xmm0", "xmm1", "xmm2"
 );
 }
 
 void LinearScaleYUVToRGB32Row(const uint8* y_buf,
                               const uint8* u_buf,
                               const uint8* v_buf,
                               uint8* rgb_buf,
                               int width,
                               int source_dx) {
-  asm(
+  asm volatile(
   "xor    %%r11,%%r11\n"   // x = 0
-  "sub    $0x2,%4\n"
+  "sub    $0x2,%[width]\n"
   "js     2f\n"
-  "cmp    $0x20000,%6\n"   // if source_dx >= 2.0
+  "cmp    $0x20000,%[source_dx]\n"   // if source_dx >= 2.0
   "jl     0f\n"
   "mov    $0x8000,%%r11\n" // x = 0.5 for 1/2 or less
 "0:"
 
 "1:"
   "mov    %%r11,%%r10\n"
   "sar    $0x11,%%r10\n"
 
-  "movzb  (%1, %%r10, 1), %%r13 \n"
-  "movzb  1(%1, %%r10, 1), %%r14 \n"
+  "movzb  (%[u_buf], %%r10, 1), %%r13 \n"
+  "movzb  1(%[u_buf], %%r10, 1), %%r14 \n"
   "mov    %%r11, %%rax \n"
   "and    $0x1fffe, %%rax \n"
   "imul   %%rax, %%r14 \n"
   "xor    $0x1fffe, %%rax \n"
   "imul   %%rax, %%r13 \n"
   "add    %%r14, %%r13 \n"
   "shr    $17, %%r13 \n"
-  "movq   2048(%5,%%r13,8), %%xmm0\n"
+  "movq   2048(%[kCoefficientsRgbY],%%r13,8), %%xmm0\n"
 
-  "movzb  (%2, %%r10, 1), %%r13 \n"
-  "movzb  1(%2, %%r10, 1), %%r14 \n"
+  "movzb  (%[v_buf], %%r10, 1), %%r13 \n"
+  "movzb  1(%[v_buf], %%r10, 1), %%r14 \n"
   "mov    %%r11, %%rax \n"
   "and    $0x1fffe, %%rax \n"
   "imul   %%rax, %%r14 \n"
   "xor    $0x1fffe, %%rax \n"
   "imul   %%rax, %%r13 \n"
   "add    %%r14, %%r13 \n"
   "shr    $17, %%r13 \n"
-  "movq   4096(%5,%%r13,8), %%xmm1\n"
+  "movq   4096(%[kCoefficientsRgbY],%%r13,8), %%xmm1\n"
 
   "mov    %%r11, %%rax \n"
-  "lea    (%%r11,%6),%%r10\n"
+  "lea    (%%r11,%[source_dx]),%%r10\n"
   "sar    $0x10,%%r11\n"
   "paddsw %%xmm1,%%xmm0\n"
 
-  "movzb  (%0, %%r11, 1), %%r13 \n"
-  "movzb  1(%0, %%r11, 1), %%r14 \n"
+  "movzb  (%[y_buf], %%r11, 1), %%r13 \n"
+  "movzb  1(%[y_buf], %%r11, 1), %%r14 \n"
   "and    $0xffff, %%rax \n"
   "imul   %%rax, %%r14 \n"
   "xor    $0xffff, %%rax \n"
   "imul   %%rax, %%r13 \n"
   "add    %%r14, %%r13 \n"
   "shr    $16, %%r13 \n"
-  "movq   (%5,%%r13,8),%%xmm1\n"
+  "movq   (%[kCoefficientsRgbY],%%r13,8),%%xmm1\n"
 
   "mov    %%r10, %%rax \n"
-  "lea    (%%r10,%6),%%r11\n"
+  "lea    (%%r10,%[source_dx]),%%r11\n"
   "sar    $0x10,%%r10\n"
 
-  "movzb  (%0,%%r10,1), %%r13 \n"
-  "movzb  1(%0,%%r10,1), %%r14 \n"
+  "movzb  (%[y_buf],%%r10,1), %%r13 \n"
+  "movzb  1(%[y_buf],%%r10,1), %%r14 \n"
   "and    $0xffff, %%rax \n"
   "imul   %%rax, %%r14 \n"
   "xor    $0xffff, %%rax \n"
   "imul   %%rax, %%r13 \n"
   "add    %%r14, %%r13 \n"
   "shr    $16, %%r13 \n"
-  "movq   (%5,%%r13,8),%%xmm2\n"
+  "movq   (%[kCoefficientsRgbY],%%r13,8),%%xmm2\n"
 
   "paddsw %%xmm0,%%xmm1\n"
   "paddsw %%xmm0,%%xmm2\n"
   "shufps $0x44,%%xmm2,%%xmm1\n"
   "psraw  $0x6,%%xmm1\n"
   "packuswb %%xmm1,%%xmm1\n"
-  "movq   %%xmm1,0x0(%3)\n"
-  "add    $0x8,%3\n"
-  "sub    $0x2,%4\n"
+  "movq   %%xmm1,0x0(%[rgb_buf])\n"
+  "add    $0x8,%[rgb_buf]\n"
+  "sub    $0x2,%[width]\n"
   "jns    1b\n"
 
 "2:"
-  "add    $0x1,%4\n"
+  "add    $0x1,%[width]\n"
   "js     3f\n"
 
   "mov    %%r11,%%r10\n"
   "sar    $0x11,%%r10\n"
 
-  "movzb  (%1,%%r10,1), %%r13 \n"
-  "movq   2048(%5,%%r13,8),%%xmm0\n"
+  "movzb  (%[u_buf],%%r10,1), %%r13 \n"
+  "movq   2048(%[kCoefficientsRgbY],%%r13,8),%%xmm0\n"
 
-  "movzb  (%2,%%r10,1), %%r13 \n"
-  "movq   4096(%5,%%r13,8),%%xmm1\n"
+  "movzb  (%[v_buf],%%r10,1), %%r13 \n"
+  "movq   4096(%[kCoefficientsRgbY],%%r13,8),%%xmm1\n"
 
   "paddsw %%xmm1,%%xmm0\n"
   "sar    $0x10,%%r11\n"
 
-  "movzb  (%0,%%r11,1), %%r13 \n"
-  "movq   (%5,%%r13,8),%%xmm1\n"
+  "movzb  (%[y_buf],%%r11,1), %%r13 \n"
+  "movq   (%[kCoefficientsRgbY],%%r13,8),%%xmm1\n"
 
   "paddsw %%xmm0,%%xmm1\n"
   "psraw  $0x6,%%xmm1\n"
   "packuswb %%xmm1,%%xmm1\n"
-  "movd   %%xmm1,0x0(%3)\n"
+  "movd   %%xmm1,0x0(%[rgb_buf])\n"
 
 "3:"
-  :
-  : "r"(y_buf),  // %0
-    "r"(u_buf),  // %1
-    "r"(v_buf),  // %2
-    "r"(rgb_buf),  // %3
-    "r"(width),  // %4
-    "r" (kCoefficientsRgbY),  // %5
-    "r"(static_cast<long>(source_dx))  // %6
-  : "memory", "r10", "r11", "r13", "r14", "rax", "xmm0", "xmm1", "xmm2"
+  : [rgb_buf] "+r"(rgb_buf),
+    [width] "+r"(width)
+  : [y_buf] "r"(y_buf),
+    [u_buf] "r"(u_buf),
+    [v_buf] "r"(v_buf),
+    [kCoefficientsRgbY] "r" (kCoefficientsRgbY),
+    [source_dx] "r"(static_cast<long>(source_dx))
+  : "cc", "memory", "r10", "r11", "r13", "r14", "rax", "xmm0", "xmm1", "xmm2"
 );
 }
 
 #elif defined(MOZILLA_MAY_SUPPORT_SSE) && defined(ARCH_CPU_X86_32) && !defined(__PIC__)
 
 // PIC version is slower because less registers are available, so
 // non-PIC is used on platforms where it is possible.
 void FastConvertYUVToRGB32Row_SSE(const uint8* y_buf,
--- a/image/ImgDrawResult.h
+++ b/image/ImgDrawResult.h
@@ -18,16 +18,22 @@ namespace image {
  *
  * Most users of ImgDrawResult will only be interested in whether the value is
  * SUCCESS or not. The other values are primarily useful for debugging and error
  * handling.
  *
  * SUCCESS: We successfully drew a completely decoded frame of the requested
  * size. Drawing again with FLAG_SYNC_DECODE would not change the result.
  *
+ * SUCCESS_NOT_COMPLETE: The image was drawn successfully and completely, but
+ * it hasn't notified about the sync-decode yet. This can only happen when
+ * layout pokes at the internal image state beforehand via
+ * nsStyleImage::StartDecoding. This should probably go away eventually,
+ * somehow, see bug 1471583.
+ *
  * INCOMPLETE: We successfully drew a frame that was partially decoded. (Note
  * that successfully drawing a partially decoded frame may not actually draw any
  * pixels!) Drawing again with FLAG_SYNC_DECODE would improve the result.
  *
  * WRONG_SIZE: We successfully drew a wrongly-sized frame that had to be scaled.
  * This is only returned if drawing again with FLAG_SYNC_DECODE would improve
  * the result; if the size requested was larger than the intrinsic size of the
  * image, for example, we would generally have to scale whether FLAG_SYNC_DECODE
@@ -44,16 +50,17 @@ namespace image {
  * BAD_IMAGE: We failed to draw because the image has an error. This is a
  * permanent condition.
  *
  * BAD_ARGS: We failed to draw because bad arguments were passed to draw().
  */
 enum class MOZ_MUST_USE_TYPE ImgDrawResult : uint8_t
 {
   SUCCESS,
+  SUCCESS_NOT_COMPLETE,
   INCOMPLETE,
   WRONG_SIZE,
   NOT_READY,
   TEMPORARY_ERROR,
   BAD_IMAGE,
   BAD_ARGS
 };
 
@@ -66,17 +73,21 @@ enum class MOZ_MUST_USE_TYPE ImgDrawResu
  * are recoverable and we want to know if any recoverable failures occurred.
  */
 inline ImgDrawResult
 operator&(const ImgDrawResult aLeft, const ImgDrawResult aRight)
 {
   if (MOZ_LIKELY(aLeft == ImgDrawResult::SUCCESS)) {
     return aRight;
   }
-  if (aLeft == ImgDrawResult::BAD_IMAGE && aRight != ImgDrawResult::SUCCESS) {
+
+  if ((aLeft == ImgDrawResult::BAD_IMAGE ||
+       aLeft == ImgDrawResult::SUCCESS_NOT_COMPLETE) &&
+      aRight != ImgDrawResult::SUCCESS &&
+      aRight != ImgDrawResult::SUCCESS_NOT_COMPLETE) {
     return aRight;
   }
   return aLeft;
 }
 
 inline ImgDrawResult&
 operator&=(ImgDrawResult& aLeft, const ImgDrawResult aRight)
 {
--- a/image/decoders/icon/android/nsIconChannel.cpp
+++ b/image/decoders/icon/android/nsIconChannel.cpp
@@ -69,17 +69,16 @@ moz_icon_to_channel(nsIURI* aURI, const 
   int width = aIconSize;
   int height = aIconSize;
 
   // moz-icon data should have two bytes for the size,
   // then the ARGB pixel values with pre-multiplied Alpha
   const int channels = 4;
   long int buf_size = 2 + channels * height * width;
   uint8_t* const buf = (uint8_t*)moz_xmalloc(buf_size);
-  NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
   uint8_t* out = buf;
 
   *(out++) = width;
   *(out++) = height;
 
   nsresult rv;
   if (XRE_IsParentProcess()) {
     rv = GetIconForExtension(aFileExt, aIconSize, out);
--- a/image/decoders/icon/gtk/nsIconChannel.cpp
+++ b/image/decoders/icon/gtk/nsIconChannel.cpp
@@ -45,17 +45,16 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPi
                  gdk_pixbuf_get_bits_per_sample(aPixbuf) == 8 &&
                  gdk_pixbuf_get_has_alpha(aPixbuf) &&
                  gdk_pixbuf_get_n_channels(aPixbuf) == 4,
                  NS_ERROR_UNEXPECTED);
 
   const int n_channels = 4;
   gsize buf_size = 2 + n_channels * height * width;
   uint8_t* const buf = (uint8_t*)moz_xmalloc(buf_size);
-  NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
   uint8_t* out = buf;
 
   *(out++) = width;
   *(out++) = height;
 
   const guchar* const pixels = gdk_pixbuf_get_pixels(aPixbuf);
   int rowextra = gdk_pixbuf_get_rowstride(aPixbuf) - width * n_channels;
 
--- a/image/imgRequestProxy.cpp
+++ b/image/imgRequestProxy.cpp
@@ -798,17 +798,17 @@ imgRequestProxy::GetMimeType(char** aMim
     return NS_ERROR_FAILURE;
   }
 
   const char* type = GetOwner()->GetMimeType();
   if (!type) {
     return NS_ERROR_FAILURE;
   }
 
-  *aMimeType = NS_strdup(type);
+  *aMimeType = NS_xstrdup(type);
 
   return NS_OK;
 }
 
 imgRequestProxy* imgRequestProxy::NewClonedProxy()
 {
   return new imgRequestProxy();
 }
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -12,16 +12,18 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>     /* for isatty() */
 #endif
 
 #include "base/basictypes.h"
 
 #include "jsapi.h"
 #include "js/AutoByteString.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceBufferHolder.h"
 
 #include "xpcpublic.h"
 
 #include "XPCShellEnvironment.h"
 
 #include "mozilla/XPCOM.h"
 
 #include "nsIChannel.h"
new file mode 100644
--- /dev/null
+++ b/js/public/CompilationAndEvaluation.h
@@ -0,0 +1,223 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/* Functions for compiling and evaluating scripts. */
+
+#ifndef js_CompilationAndEvaluation_h
+#define js_CompilationAndEvaluation_h
+
+#include <stddef.h> // size_t
+#include <stdio.h> // FILE
+
+#include "jstypes.h" // JS_PUBLIC_API
+
+#include "js/CompileOptions.h" // JS::CompileOptions, JS::ReadOnlyCompileOptions
+#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle
+
+struct JSContext;
+class JSFunction;
+class JSObject;
+class JSScript;
+
+namespace JS {
+
+template<typename T> class AutoVector;
+
+class SourceBufferHolder;
+union Value;
+
+} // namespace JS
+
+/**
+ * Given a buffer, return false if the buffer might become a valid JavaScript
+ * script with the addition of more lines, or true if the validity of such a
+ * script is conclusively known (because it's the prefix of a valid script --
+ * and possibly the entirety of such a script).
+ *
+ * The intent of this function is to enable interactive compilation: accumulate
+ * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+ * the compiler.
+ */
+extern JS_PUBLIC_API(bool)
+JS_BufferIsCompilableUnit(JSContext* cx, JS::Handle<JSObject*> obj, const char* utf8,
+                          size_t length);
+
+/*
+ * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either
+ * they use the global as the scope, or they take an AutoObjectVector of objects
+ * to use as the scope chain.  In the former case, the global is also used as
+ * the "this" keyword value and the variables object (ECMA parlance for where
+ * 'var' and 'function' bind names) of the execution context for script.  In the
+ * latter case, the first object in the provided list is used, unless the list
+ * is empty, in which case the global is used.
+ *
+ * Why a runtime option?  The alternative is to add APIs duplicating those
+ * for the other value of flags, and that doesn't seem worth the code bloat
+ * cost.  Such new entry points would probably have less obvious names, too, so
+ * would not tend to be used.  The ContextOptionsRef adjustment, OTOH, can be
+ * more easily hacked into existing code that does not depend on the bug; such
+ * code can continue to use the familiar JS::Evaluate, etc., entry points.
+ */
+
+/**
+ * Evaluate a script in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::Handle<JSScript*> script, JS::MutableHandle<JS::Value> rval);
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::Handle<JSScript*> script);
+
+/**
+ * As above, but providing an explicit scope chain.  envChain must not include
+ * the global object on it; that's implicit.  It needs to contain the other
+ * objects that should end up on the script's scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::AutoVector<JSObject*>& envChain,
+                 JS::Handle<JSScript*> script, JS::MutableHandle<JS::Value> rval);
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::AutoVector<JSObject*>& envChain, JS::Handle<JSScript*> script);
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
+                 const JS::CompileOptions& options,
+                 JS::MutableHandle<JSScript*> script);
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
+                   const JS::CompileOptions& options,
+                   JS::MutableHandle<JSScript*> script);
+
+namespace JS {
+
+/**
+ * Like the above, but handles a cross-compartment script. If the script is
+ * cross-compartment, it is cloned into the current compartment before executing.
+ */
+extern JS_PUBLIC_API(bool)
+CloneAndExecuteScript(JSContext* cx, Handle<JSScript*> script, MutableHandle<Value> rval);
+
+/**
+ * Like CloneAndExecuteScript above, but allows executing under a non-syntactic
+ * environment chain.
+ */
+extern JS_PUBLIC_API(bool)
+CloneAndExecuteScript(JSContext* cx, AutoVector<JSObject*>& envChain, Handle<JSScript*> script,
+                      MutableHandle<Value> rval);
+
+/**
+ * Evaluate the given source buffer in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+         SourceBufferHolder& srcBuf, MutableHandle<Value> rval);
+
+/**
+ * As above, but providing an explicit scope chain.  envChain must not include
+ * the global object on it; that's implicit.  It needs to contain the other
+ * objects that should end up on the script's scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, AutoVector<JSObject*>& envChain, const ReadOnlyCompileOptions& options,
+         SourceBufferHolder& srcBuf, MutableHandle<Value> rval);
+
+/**
+ * Evaluate the given byte buffer in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+         const char* bytes, size_t length, MutableHandle<Value> rval);
+
+/**
+ * Evaluate the given file in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+         const char* filename, MutableHandle<Value> rval);
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+        SourceBufferHolder& srcBuf, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+        const char* bytes, size_t length, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+        FILE* file, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+        const char* filename, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+                            SourceBufferHolder& srcBuf, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+                            const char* bytes, size_t length, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+                            FILE* file, MutableHandle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+                            const char* filename, MutableHandle<JSScript*> script);
+
+/**
+ * Compile a function with envChain plus the global as its scope chain.
+ * envChain must contain objects in the current compartment of cx.  The actual
+ * scope chain used for the function will consist of With wrappers for those
+ * objects, followed by the current global of the compartment cx is in.  This
+ * global must not be explicitly included in the scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext* cx, AutoVector<JSObject*>& envChain,
+                const ReadOnlyCompileOptions& options,
+                const char* name, unsigned nargs, const char* const* argnames,
+                SourceBufferHolder& srcBuf, MutableHandle<JSFunction*> fun);
+
+/**
+ * Same as above, but taking a const char * for the function body.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext* cx, AutoVector<JSObject*>& envChain,
+                const ReadOnlyCompileOptions& options,
+                const char* name, unsigned nargs, const char* const* argnames,
+                const char* bytes, size_t length, MutableHandle<JSFunction*> fun);
+
+/*
+ * Associate an element wrapper and attribute name with a previously compiled
+ * script, for debugging purposes. Calling this function is optional, but should
+ * be done before script execution if it is required.
+ */
+extern JS_PUBLIC_API(bool)
+InitScriptSourceElement(JSContext* cx, Handle<JSScript*> script,
+                        Handle<JSObject*> element, Handle<JSString*> elementAttrName = nullptr);
+
+/*
+ * For a script compiled with the hideScriptFromDebugger option, expose the
+ * script to the debugger by calling the debugger's onNewScript hook.
+ */
+extern JS_PUBLIC_API(void)
+ExposeScriptToDebugger(JSContext* cx, Handle<JSScript*> script);
+
+} /* namespace JS */
+
+#endif /* js_CompilationAndEvaluation_h */
new file mode 100644
--- /dev/null
+++ b/js/public/CompileOptions.h
@@ -0,0 +1,542 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ * Options for JavaScript compilation.
+ *
+ * In the most common use case, a CompileOptions instance is allocated on the
+ * stack, and holds non-owning references to non-POD option values: strings,
+ * principals, objects, and so on.  The code declaring the instance guarantees
+ * that such option values will outlive the CompileOptions itself: objects are
+ * otherwise rooted, principals have had their reference counts bumped, and
+ * strings won't be freed until the CompileOptions goes out of scope.  In this
+ * situation, CompileOptions only refers to things others own, so it can be
+ * lightweight.
+ *
+ * In some cases, however, we need to hold compilation options with a
+ * non-stack-like lifetime.  For example, JS::CompileOffThread needs to save
+ * compilation options where a worker thread can find them, then return
+ * immediately.  The worker thread will come along at some later point, and use
+ * the options.
+ *
+ * The compiler itself just needs to be able to access a collection of options;
+ * it doesn't care who owns them, or what's keeping them alive.  It does its
+ * own addrefs/copies/tracing/etc.
+ *
+ * Furthermore, in some cases compile options are propagated from one entity to
+ * another (e.g. from a script to a function defined in that script).  This
+ * involves copying over some, but not all, of the options.
+ *
+ * So we have a class hierarchy that reflects these four use cases:
+ *
+ * - TransitiveCompileOptions is the common base class, representing options
+ *   that should get propagated from a script to functions defined in that
+ *   script.  This class is abstract and is only ever used as a subclass.
+ *
+ * - ReadOnlyCompileOptions is the only subclass of TransitiveCompileOptions,
+ *   representing a full set of compile options.  It can be used by code that
+ *   simply needs to access options set elsewhere, like the compiler.  This
+ *   class too is abstract and is only ever used as a subclass.
+ *
+ * - The usual CompileOptions class must be stack-allocated, and holds
+ *   non-owning references to the filename, element, and so on. It's derived
+ *   from ReadOnlyCompileOptions, so the compiler can use it.
+ *
+ * - OwningCompileOptions roots / copies / reference counts of all its values,
+ *   and unroots / frees / releases them when it is destructed. It too is
+ *   derived from ReadOnlyCompileOptions, so the compiler accepts it.
+ */
+
+#ifndef js_CompileOptions_h
+#define js_CompileOptions_h
+
+#include "mozilla/Attributes.h" // MOZ_MUST_USE
+#include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf
+
+#include <stddef.h> // size_t
+#include <stdint.h> // uint8_t
+
+#include "jstypes.h" // JS_PUBLIC_API
+
+#include "js/RootingAPI.h" // JS::PersistentRooted, JS::Rooted
+
+struct JSContext;
+class JSObject;
+class JSScript;
+class JSString;
+
+namespace JS {
+
+enum class AsmJSOption : uint8_t
+{
+    Enabled,
+    Disabled,
+    DisabledByDebugger,
+};
+
+/**
+ * The common base class for the CompileOptions hierarchy.
+ *
+ * Use this in code that needs to propagate compile options from one
+ * compilation unit to another.
+ */
+class JS_PUBLIC_API(TransitiveCompileOptions)
+{
+  protected:
+    /**
+     * The Web Platform allows scripts to be loaded from arbitrary cross-origin
+     * sources. This allows an attack by which a malicious website loads a
+     * sensitive file (say, a bank statement) cross-origin (using the user's
+     * cookies), and sniffs the generated syntax errors (via a window.onerror
+     * handler) for juicy morsels of its contents.
+     *
+     * To counter this attack, HTML5 specifies that script errors should be
+     * sanitized ("muted") when the script is not same-origin with the global
+     * for which it is loaded. Callers should set this flag for cross-origin
+     * scripts, and it will be propagated appropriately to child scripts and
+     * passed back in JSErrorReports.
+     */
+    bool mutedErrors_ = false;
+
+    const char* filename_ = nullptr;
+    const char* introducerFilename_ = nullptr;
+    const char16_t* sourceMapURL_ = nullptr;
+
+  public:
+    // POD options.
+    bool utf8 = false;
+    bool selfHostingMode = false;
+    bool canLazilyParse = true;
+    bool strictOption = false;
+    bool extraWarningsOption = false;
+    bool werrorOption = false;
+    AsmJSOption asmJSOption = AsmJSOption::Disabled;
+    bool throwOnAsmJSValidationFailureOption = false;
+    bool forceAsync = false;
+    bool sourceIsLazy = false;
+    bool allowHTMLComments = true;
+    bool isProbablySystemCode = false;
+    bool hideScriptFromDebugger = false;
+
+    /**
+     * |introductionType| is a statically allocated C string: one of "eval",
+     * "Function", or "GeneratorFunction".
+     */
+    const char* introductionType = nullptr;
+
+    unsigned introductionLineno = 0;
+    uint32_t introductionOffset = 0;
+    bool hasIntroductionInfo = false;
+
+  protected:
+    TransitiveCompileOptions() = default;
+
+    // Set all POD options (those not requiring reference counts, copies,
+    // rooting, or other hand-holding) to their values in |rhs|.
+    void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
+
+  public:
+    // Read-only accessors for non-POD options. The proper way to set these
+    // depends on the derived type.
+    bool mutedErrors() const { return mutedErrors_; }
+    const char* filename() const { return filename_; }
+    const char* introducerFilename() const { return introducerFilename_; }
+    const char16_t* sourceMapURL() const { return sourceMapURL_; }
+    virtual JSObject* element() const = 0;
+    virtual JSString* elementAttributeName() const = 0;
+    virtual JSScript* introductionScript() const = 0;
+
+  private:
+    void operator=(const TransitiveCompileOptions&) = delete;
+};
+
+class JS_PUBLIC_API(CompileOptions);
+
+/**
+ * The class representing a full set of compile options.
+ *
+ * Use this in code that only needs to access compilation options created
+ * elsewhere, like the compiler.  Don't instantiate this class (the constructor
+ * is protected anyway); instead, create instances only of the derived classes:
+ * CompileOptions and OwningCompileOptions.
+ */
+class JS_PUBLIC_API(ReadOnlyCompileOptions)
+  : public TransitiveCompileOptions
+{
+  public:
+    // POD options.
+    unsigned lineno  = 1;
+    unsigned column = 0;
+
+    // The offset within the ScriptSource's full uncompressed text of the first
+    // character we're presenting for compilation with this CompileOptions.
+    //
+    // When we compile a LazyScript, we pass the compiler only the substring of
+    // the source the lazy function occupies. With chunked decompression, we
+    // may not even have the complete uncompressed source present in memory. But
+    // parse node positions are offsets within the ScriptSource's full text,
+    // and LazyScripts indicate their substring of the full source by its
+    // starting and ending offsets within the full text. This
+    // scriptSourceOffset field lets the frontend convert between these
+    // offsets and offsets within the substring presented for compilation.
+    unsigned scriptSourceOffset = 0;
+
+    // isRunOnce only applies to non-function scripts.
+    bool isRunOnce =  false;
+
+    bool nonSyntacticScope = false;
+    bool noScriptRval = false;
+    bool allowSyntaxParser = true;
+
+
+  private:
+    friend class CompileOptions;
+
+  protected:
+    ReadOnlyCompileOptions() = default;
+
+    // Set all POD options (those not requiring reference counts, copies,
+    // rooting, or other hand-holding) to their values in |rhs|.
+    void copyPODOptions(const ReadOnlyCompileOptions& rhs);
+
+  public:
+    // Read-only accessors for non-POD options. The proper way to set these
+    // depends on the derived type.
+    bool mutedErrors() const { return mutedErrors_; }
+    const char* filename() const { return filename_; }
+    const char* introducerFilename() const { return introducerFilename_; }
+    const char16_t* sourceMapURL() const { return sourceMapURL_; }
+    virtual JSObject* element() const override = 0;
+    virtual JSString* elementAttributeName() const override = 0;
+    virtual JSScript* introductionScript() const override = 0;
+
+  private:
+    void operator=(const ReadOnlyCompileOptions&) = delete;
+};
+
+/**
+ * Compilation options, with dynamic lifetime. An instance of this type
+ * makes a copy of / holds / roots all dynamically allocated resources
+ * (principals; elements; strings) that it refers to. Its destructor frees
+ * / drops / unroots them. This is heavier than CompileOptions, below, but
+ * unlike CompileOptions, it can outlive any given stack frame.
+ *
+ * Note that this *roots* any JS values it refers to - they're live
+ * unconditionally. Thus, instances of this type can't be owned, directly
+ * or indirectly, by a JavaScript object: if any value that this roots ever
+ * comes to refer to the object that owns this, then the whole cycle, and
+ * anything else it entrains, will never be freed.
+ */
+class JS_PUBLIC_API(OwningCompileOptions) final
+  : public ReadOnlyCompileOptions
+{
+    PersistentRooted<JSObject*> elementRoot;
+    PersistentRooted<JSString*> elementAttributeNameRoot;
+    PersistentRooted<JSScript*> introductionScriptRoot;
+
+  public:
+    // A minimal constructor, for use with OwningCompileOptions::copy.
+    explicit OwningCompileOptions(JSContext* cx);
+    ~OwningCompileOptions();
+
+    JSObject* element() const override { return elementRoot; }
+    JSString* elementAttributeName() const override { return elementAttributeNameRoot; }
+    JSScript* introductionScript() const override { return introductionScriptRoot; }
+
+    /** Set this to a copy of |rhs|.  Return false on OOM. */
+    bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
+
+    /* These setters make copies of their string arguments and are fallible. */
+    bool setFile(JSContext* cx, const char* f);
+    MOZ_MUST_USE bool setFileAndLine(JSContext* cx, const char* f, unsigned l);
+    MOZ_MUST_USE bool setSourceMapURL(JSContext* cx, const char16_t* s);
+    MOZ_MUST_USE bool setIntroducerFilename(JSContext* cx, const char* s);
+
+    /* These setters are infallible, and can be chained. */
+
+    OwningCompileOptions& setLine(unsigned l) {
+        lineno = l;
+        return *this;
+    }
+
+    OwningCompileOptions& setElement(JSObject* e) {
+        elementRoot = e;
+        return *this;
+    }
+
+    OwningCompileOptions& setElementAttributeName(JSString* p) {
+        elementAttributeNameRoot = p;
+        return *this;
+    }
+
+    OwningCompileOptions& setIntroductionScript(JSScript* s) {
+        introductionScriptRoot = s;
+        return *this;
+    }
+
+    OwningCompileOptions& setMutedErrors(bool mute) {
+        mutedErrors_ = mute;
+        return *this;
+    }
+
+    OwningCompileOptions& setUTF8(bool u) {
+        utf8 = u;
+        return *this;
+    }
+
+    OwningCompileOptions& setColumn(unsigned c) {
+        column = c;
+        return *this;
+    }
+
+    OwningCompileOptions& setScriptSourceOffset(unsigned o) {
+        scriptSourceOffset = o;
+        return *this;
+    }
+
+    OwningCompileOptions& setIsRunOnce(bool once) {
+        isRunOnce = once;
+        return *this;
+    }
+
+    OwningCompileOptions& setNoScriptRval(bool nsr) {
+        noScriptRval = nsr;
+        return *this;
+    }
+
+    OwningCompileOptions& setSelfHostingMode(bool shm) {
+        selfHostingMode = shm;
+        return *this;
+    }
+
+    OwningCompileOptions& setCanLazilyParse(bool clp) {
+        canLazilyParse = clp;
+        return *this;
+    }
+
+    OwningCompileOptions& setAllowSyntaxParser(bool clp) {
+        allowSyntaxParser = clp;
+        return *this;
+    }
+
+    OwningCompileOptions& setSourceIsLazy(bool l) {
+        sourceIsLazy = l;
+        return *this;
+    }
+
+    OwningCompileOptions& setNonSyntacticScope(bool n) {
+        nonSyntacticScope = n;
+        return *this;
+    }
+
+    OwningCompileOptions& setIntroductionType(const char* t) {
+        introductionType = t;
+        return *this;
+    }
+
+    bool setIntroductionInfo(JSContext* cx, const char* introducerFn,
+                             const char* intro, unsigned line,
+                             JSScript* script, uint32_t offset)
+    {
+        if (!setIntroducerFilename(cx, introducerFn))
+            return false;
+
+        introductionType = intro;
+        introductionLineno = line;
+        introductionScriptRoot = script;
+        introductionOffset = offset;
+        hasIntroductionInfo = true;
+        return true;
+    }
+
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+  private:
+    void operator=(const CompileOptions& rhs) = delete;
+};
+
+/**
+ * Compilation options stored on the stack. An instance of this type
+ * simply holds references to dynamically allocated resources (element;
+ * filename; source map URL) that are owned by something else. If you
+ * create an instance of this type, it's up to you to guarantee that
+ * everything you store in it will outlive it.
+ */
+class MOZ_STACK_CLASS JS_PUBLIC_API(CompileOptions) final
+  : public ReadOnlyCompileOptions
+{
+  private:
+    Rooted<JSObject*> elementRoot;
+    Rooted<JSString*> elementAttributeNameRoot;
+    Rooted<JSScript*> introductionScriptRoot;
+
+  public:
+    explicit CompileOptions(JSContext* cx);
+
+    CompileOptions(JSContext* cx, const ReadOnlyCompileOptions& rhs)
+      : ReadOnlyCompileOptions(),
+        elementRoot(cx),
+        elementAttributeNameRoot(cx),
+        introductionScriptRoot(cx)
+    {
+        copyPODOptions(rhs);
+
+        filename_ = rhs.filename();
+        introducerFilename_ = rhs.introducerFilename();
+        sourceMapURL_ = rhs.sourceMapURL();
+        elementRoot = rhs.element();
+        elementAttributeNameRoot = rhs.elementAttributeName();
+        introductionScriptRoot = rhs.introductionScript();
+    }
+
+    CompileOptions(JSContext* cx, const TransitiveCompileOptions& rhs)
+      : ReadOnlyCompileOptions(),
+        elementRoot(cx),
+        elementAttributeNameRoot(cx),
+        introductionScriptRoot(cx)
+    {
+        copyPODTransitiveOptions(rhs);
+
+        filename_ = rhs.filename();
+        introducerFilename_ = rhs.introducerFilename();
+        sourceMapURL_ = rhs.sourceMapURL();
+        elementRoot = rhs.element();
+        elementAttributeNameRoot = rhs.elementAttributeName();
+        introductionScriptRoot = rhs.introductionScript();
+    }
+
+    JSObject* element() const override {
+        return elementRoot;
+    }
+
+    JSString* elementAttributeName() const override {
+        return elementAttributeNameRoot;
+    }
+
+    JSScript* introductionScript() const override {
+        return introductionScriptRoot;
+    }
+
+    CompileOptions& setFile(const char* f) {
+        filename_ = f;
+        return *this;
+    }
+
+    CompileOptions& setLine(unsigned l) {
+        lineno = l;
+        return *this;
+    }
+
+    CompileOptions& setFileAndLine(const char* f, unsigned l) {
+        filename_ = f;
+        lineno = l;
+        return *this;
+    }
+
+    CompileOptions& setSourceMapURL(const char16_t* s) {
+        sourceMapURL_ = s;
+        return *this;
+    }
+
+    CompileOptions& setElement(JSObject* e) {
+        elementRoot = e;
+        return *this;
+    }
+
+    CompileOptions& setElementAttributeName(JSString* p) {
+        elementAttributeNameRoot = p;
+        return *this;
+    }
+
+    CompileOptions& setIntroductionScript(JSScript* s) {
+        introductionScriptRoot = s;
+        return *this;
+    }
+
+    CompileOptions& setMutedErrors(bool mute) {
+        mutedErrors_ = mute;
+        return *this;
+    }
+
+    CompileOptions& setUTF8(bool u) {
+        utf8 = u;
+        return *this;
+    }
+
+    CompileOptions& setColumn(unsigned c) {
+        column = c;
+        return *this;
+    }
+
+    CompileOptions& setScriptSourceOffset(unsigned o) {
+        scriptSourceOffset = o;
+        return *this;
+    }
+
+    CompileOptions& setIsRunOnce(bool once) {
+        isRunOnce = once;
+        return *this;
+    }
+
+    CompileOptions& setNoScriptRval(bool nsr) {
+        noScriptRval = nsr;
+        return *this;
+    }
+
+    CompileOptions& setSelfHostingMode(bool shm) {
+        selfHostingMode = shm;
+        return *this;
+    }
+
+    CompileOptions& setCanLazilyParse(bool clp) {
+        canLazilyParse = clp;
+        return *this;
+    }
+
+    CompileOptions& setAllowSyntaxParser(bool clp) {
+        allowSyntaxParser = clp;
+        return *this;
+    }
+
+    CompileOptions& setSourceIsLazy(bool l) {
+        sourceIsLazy = l;
+        return *this;
+    }
+
+    CompileOptions& setNonSyntacticScope(bool n) {
+        nonSyntacticScope = n;
+        return *this;
+    }
+
+    CompileOptions& setIntroductionType(const char* t) {
+        introductionType = t;
+        return *this;
+    }
+
+    CompileOptions& setIntroductionInfo(const char* introducerFn,
+                                        const char* intro, unsigned line,
+                                        JSScript* script, uint32_t offset)
+    {
+        introducerFilename_ = introducerFn;
+        introductionType = intro;
+        introductionLineno = line;
+        introductionScriptRoot = script;
+        introductionOffset = offset;
+        hasIntroductionInfo = true;
+        return *this;
+    }
+
+    CompileOptions& maybeMakeStrictMode(bool strict) {
+        strictOption = strictOption || strict;
+        return *this;
+    }
+
+  private:
+    void operator=(const CompileOptions& rhs) = delete;
+};
+
+} // namespace JS
+
+#endif /* js_CompileOptions_h */
new file mode 100644
--- /dev/null
+++ b/js/public/OffThreadScriptCompilation.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ * Types and functions related to the compilation of JavaScript off the
+ * direct JSAPI-using thread.
+ */
+
+#ifndef js_OffThreadScriptCompilation_h
+#define js_OffThreadScriptCompilation_h
+
+#include "mozilla/Range.h" // mozilla::Range
+#include "mozilla/Vector.h" // mozilla::Vector
+
+#include <stddef.h> // size_t
+
+#include "jstypes.h" // JS_PUBLIC_API
+
+#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions
+#include "js/GCVector.h" // JS::GCVector
+#include "js/Transcoding.h" // JS::TranscodeSource
+
+struct JSContext;
+class JSScript;
+
+namespace JS {
+
+class SourceBufferHolder;
+
+} // namespace JS
+
+namespace JS {
+
+class OffThreadToken;
+
+using OffThreadCompileCallback = void (*)(OffThreadToken* token, void* callbackData);
+
+extern JS_PUBLIC_API(bool)
+CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
+
+extern JS_PUBLIC_API(bool)
+CanDecodeOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
+
+/*
+ * Off thread compilation control flow.
+ *
+ * After successfully triggering an off thread compile of a script, the
+ * callback will eventually be invoked with the specified data and a token
+ * for the compilation. The callback will be invoked while off thread,
+ * so must ensure that its operations are thread safe. Afterwards, one of the
+ * following functions must be invoked on the runtime's main thread:
+ *
+ * - FinishOffThreadScript, to get the result script (or nullptr on failure).
+ * - CancelOffThreadScript, to free the resources without creating a script.
+ *
+ * The characters passed in to CompileOffThread must remain live until the
+ * callback is invoked, and the resulting script will be rooted until the call
+ * to FinishOffThreadScript.
+ */
+
+extern JS_PUBLIC_API(bool)
+CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, SourceBufferHolder& srcBuf,
+                 OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSScript*)
+FinishOffThreadScript(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadScript(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(bool)
+CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+                       SourceBufferHolder& srcBuf, OffThreadCompileCallback callback,
+                       void* callbackData);
+
+extern JS_PUBLIC_API(JSScript*)
+FinishOffThreadModule(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadModule(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(bool)
+DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
+                      mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
+                      OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(bool)
+DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
+                      const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
+                      OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSScript*)
+FinishOffThreadScriptDecoder(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadScriptDecoder(JSContext* cx, OffThreadToken* token);
+
+extern JS_PUBLIC_API(bool)
+DecodeMultiOffThreadScripts(JSContext* cx, const ReadOnlyCompileOptions& options,
+                            mozilla::Vector<TranscodeSource>& sources,
+                            OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(bool)
+FinishMultiOffThreadScriptsDecoder(JSContext* cx, OffThreadToken* token,
+                                   MutableHandle<GCVector<JSScript*>> scripts);
+
+extern JS_PUBLIC_API(void)
+CancelMultiOffThreadScriptsDecoder(JSContext* cx, OffThreadToken* token);
+
+} // namespace JS
+
+#endif /* js_OffThreadScriptCompilation_h */
new file mode 100644
--- /dev/null
+++ b/js/public/SourceBufferHolder.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ * SourceBufferHolder groups buffer and length values and provides a way to
+ * optionally pass ownership of the buffer to the JS engine without copying.
+ *
+ * Rules for use:
+ *
+ *  1) The data array must be allocated with js_malloc() or js_realloc() if
+ *     ownership is being granted to the SourceBufferHolder.
+ *  2) If ownership is not given to the SourceBufferHolder, then the memory
+ *     must be kept alive until the JS compilation is complete.
+ *  3) Any code calling SourceBufferHolder::take() must guarantee to keep the
+ *     memory alive until JS compilation completes.  Normally only the JS
+ *     engine should be calling take().
+ *
+ * Example use:
+ *
+ *    size_t length = 512;
+ *    char16_t* chars = js_pod_malloc<char16_t>(length);
+ *    JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
+ *    JS::Compile(cx, options, srcBuf);
+ */
+
+#ifndef js_SourceBufferHolder_h
+#define js_SourceBufferHolder_h
+
+#include "mozilla/Assertions.h" // MOZ_ASSERT
+
+#include <stddef.h> // size_t
+
+#include "js/Utility.h" // JS::UniqueTwoByteChars
+
+namespace JS {
+
+class SourceBufferHolder final
+{
+  private:
+    const char16_t* data_;
+    size_t length_;
+    bool ownsChars_;
+
+  private:
+    void fixEmptyBuffer() {
+        // Ensure that null buffers properly return an unowned, empty,
+        // null-terminated string.
+        static const char16_t NullChar_ = 0;
+        if (!data_) {
+            data_ = &NullChar_;
+            length_ = 0;
+            ownsChars_ = false;
+        }
+    }
+
+  public:
+    enum Ownership {
+      NoOwnership,
+      GiveOwnership
+    };
+
+    SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership)
+      : data_(data),
+        length_(dataLength),
+        ownsChars_(ownership == GiveOwnership)
+    {
+        fixEmptyBuffer();
+    }
+
+    SourceBufferHolder(UniqueTwoByteChars&& data, size_t dataLength)
+      : data_(data.release()),
+        length_(dataLength),
+        ownsChars_(true)
+    {
+        fixEmptyBuffer();
+    }
+
+    SourceBufferHolder(SourceBufferHolder&& other)
+      : data_(other.data_),
+        length_(other.length_),
+        ownsChars_(other.ownsChars_)
+    {
+        other.data_ = nullptr;
+        other.length_ = 0;
+        other.ownsChars_ = false;
+    }
+
+    ~SourceBufferHolder() {
+        if (ownsChars_)
+            js_free(const_cast<char16_t*>(data_));
+    }
+
+    /** Access the underlying source buffer without affecting ownership. */
+    const char16_t* get() const {
+        return data_;
+    }
+
+    /** Length of the source buffer in char16_t code units (not bytes). */
+    size_t length() const {
+        return length_;
+    }
+
+    /**
+     * Returns true if the SourceBufferHolder owns the buffer and will free it
+     * upon destruction.  If true, it is legal to call take().
+     */
+    bool ownsChars() const {
+        return ownsChars_;
+    }
+
+    /**
+     * Retrieve and take ownership of the underlying data buffer.  The caller
+     * is now responsible for calling js_free() on the returned value, *but
+     * only after JS script compilation has completed*.
+     *
+     * After the buffer has been taken the SourceBufferHolder functions as if
+     * it had been constructed on an unowned buffer;  get() and length() still
+     * work.  In order for this to be safe the taken buffer must be kept alive
+     * until after JS script compilation completes as noted above.
+     *
+     * It's the caller's responsibility to check ownsChars() before taking the
+     * buffer.  Taking and then free'ing an unowned buffer will have dire
+     * consequences.
+     */
+    char16_t* take() {
+        MOZ_ASSERT(ownsChars_);
+        ownsChars_ = false;
+        return const_cast<char16_t*>(data_);
+    }
+
+  private:
+    SourceBufferHolder(SourceBufferHolder&) = delete;
+    SourceBufferHolder& operator=(SourceBufferHolder&) = delete;
+};
+
+} // namespace JS
+
+#endif /* js_SourceBufferHolder_h */
new file mode 100644
--- /dev/null
+++ b/js/public/Transcoding.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ * Structures and functions for transcoding compiled scripts and functions to
+ * and from memory.
+ */
+
+#ifndef js_Transcoding_h
+#define js_Transcoding_h
+
+#include "mozilla/Range.h" // mozilla::Range
+#include "mozilla/Vector.h" // mozilla::Vector
+
+#include <stddef.h> // size_t
+#include <stdint.h> // uint8_t, uint32_t
+
+#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle
+
+struct JSContext;
+class JSFunction;
+class JSObject;
+class JSScript;
+
+namespace JS {
+
+using TranscodeBuffer = mozilla::Vector<uint8_t>;
+using TranscodeRange = mozilla::Range<uint8_t>;
+
+struct TranscodeSource final
+{
+    TranscodeSource(const TranscodeRange& range_, const char* file, uint32_t line)
+        : range(range_), filename(file), lineno(line)
+    {}
+
+    const TranscodeRange range;
+    const char* filename;
+    const uint32_t lineno;
+};
+
+using TranscodeSources = mozilla::Vector<TranscodeSource>;
+
+enum TranscodeResult : uint8_t
+{
+    // Successful encoding / decoding.
+    TranscodeResult_Ok = 0,
+
+    // A warning message, is set to the message out-param.
+    TranscodeResult_Failure = 0x10,
+    TranscodeResult_Failure_BadBuildId =          TranscodeResult_Failure | 0x1,
+    TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
+    TranscodeResult_Failure_AsmJSNotSupported =   TranscodeResult_Failure | 0x3,
+    TranscodeResult_Failure_BadDecode =           TranscodeResult_Failure | 0x4,
+    TranscodeResult_Failure_WrongCompileOption =  TranscodeResult_Failure | 0x5,
+    TranscodeResult_Failure_NotInterpretedFun =   TranscodeResult_Failure | 0x6,
+
+    // There is a pending exception on the context.
+    TranscodeResult_Throw = 0x20
+};
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeScript(JSContext* cx, TranscodeBuffer& buffer, Handle<JSScript*> script);
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, Handle<JSObject*> funobj);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeScript(JSContext* cx, TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
+             size_t cursorIndex = 0);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeScript(JSContext* cx, const TranscodeRange& range, MutableHandle<JSScript*> scriptp);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, MutableHandle<JSFunction*> funp,
+                          size_t cursorIndex = 0);
+
+// Register an encoder on the given script source, such that all functions can
+// be encoded as they are parsed. This strategy is used to avoid blocking the
+// main thread in a non-interruptible way.
+//
+// The |script| argument of |StartIncrementalEncoding| and
+// |FinishIncrementalEncoding| should be the top-level script returned either as
+// an out-param of any of the |Compile| functions, or the result of
+// |FinishOffThreadScript|.
+//
+// The |buffer| argument of |FinishIncrementalEncoding| is used for appending
+// the encoded bytecode into the buffer. If any of these functions failed, the
+// content of |buffer| would be undefined.
+extern JS_PUBLIC_API(bool)
+StartIncrementalEncoding(JSContext* cx, Handle<JSScript*> script);
+
+extern JS_PUBLIC_API(bool)
+FinishIncrementalEncoding(JSContext* cx, Handle<JSScript*> script, TranscodeBuffer& buffer);
+
+} // namespace JS
+
+#endif /* js_Transcoding_h */
--- a/js/rust/etc/wrapper.hpp
+++ b/js/rust/etc/wrapper.hpp
@@ -8,18 +8,21 @@
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
 
 typedef uint32_t HashNumber;
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/CompileOptions.h"
 #include "js/Conversions.h"
 #include "js/Initialization.h"
 #include "js/MemoryMetrics.h"
+#include "js/SourceBufferHolder.h"
 #include "js/StructuredClone.h"
 
 // Replacements for types that are too difficult for rust-bindgen.
 
 /// <div rustbindgen replaces="JS::detail::MaybeWrapped" />
 template <typename T>
 using replaces_MaybeWrapped = T;
--- a/js/src/NamespaceImports.h
+++ b/js/src/NamespaceImports.h
@@ -95,23 +95,18 @@ using JS::IdVector;
 using JS::ScriptVector;
 
 using JS::GCVector;
 using JS::GCHashMap;
 using JS::GCHashSet;
 
 using JS::CallArgs;
 using JS::CallNonGenericMethod;
-using JS::CompileOptions;
 using JS::IsAcceptableThis;
 using JS::NativeImpl;
-using JS::OwningCompileOptions;
-using JS::ReadOnlyCompileOptions;
-using JS::SourceBufferHolder;
-using JS::TransitiveCompileOptions;
 
 using JS::Rooted;
 using JS::RootedFunction;
 using JS::RootedId;
 using JS::RootedObject;
 using JS::RootedScript;
 using JS::RootedString;
 using JS::RootedSymbol;
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -6,32 +6,35 @@
 
 #include "builtin/Eval.h"
 
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Range.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "gc/HashUtil.h"
+#include "js/SourceBufferHolder.h"
 #include "js/StableStringChars.h"
 #include "vm/Debugger.h"
 #include "vm/GlobalObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSONParser.h"
 
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 
 using mozilla::AddToHash;
 using mozilla::HashString;
 using mozilla::RangedPtr;
 
 using JS::AutoCheckCannotGC;
 using JS::AutoStableStringChars;
+using JS::CompileOptions;
+using JS::SourceBufferHolder;
 
 // We should be able to assert this for *any* fp->environmentChain().
 static void
 AssertInnerizedEnvironmentChain(JSContext* cx, JSObject& env)
 {
 #ifdef DEBUG
     RootedObject obj(cx);
     for (obj = &env; obj; obj = obj->enclosingEnvironment())
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -10,28 +10,63 @@
 #include "builtin/SelfHostingDefines.h"
 #include "threading/ConditionVariable.h"
 #include "threading/Mutex.h"
 #include "vm/NativeObject.h"
 
 namespace js {
 
 enum PromiseSlots {
+    // Int32 value with PROMISE_FLAG_* flags below.
     PromiseSlot_Flags = 0,
+
+    // * if this promise is pending, reaction objects
+    //     * undefined if there's no reaction
+    //     * maybe-wrapped PromiseReactionRecord if there's only one reacion
+    //     * dense array if there are two or more more reactions
+    // * if this promise is fulfilled, the resolution value
+    // * if this promise is rejected, the reason for the rejection
     PromiseSlot_ReactionsOrResult,
+
+    // * if this promise is pending, resolve/reject functions.
+    //   This slot holds only the reject function. The resolve function is
+    //   reachable from the reject function's extended slot.
+    // * if this promise is either fulfilled or rejected, undefined
+    // * (special case) if this promise is the return value of an async function
+    //   invocation, the generator object for the function's internal generator
     PromiseSlot_RejectFunction,
     PromiseSlot_AwaitGenerator = PromiseSlot_RejectFunction,
+
+    // Promise object's debug info, which is created on demand.
+    // * if this promise has no debug info, undefined
+    // * if this promise contains only its process-unique ID, the ID's number
+    //   value
+    // * otherwise a PromiseDebugInfo object
     PromiseSlot_DebugInfo,
+
     PromiseSlots,
 };
 
+// This promise is either fulfilled or rejected.
+// If this flag is not set, this promise is pending.
 #define PROMISE_FLAG_RESOLVED  0x1
+
+// If this flag and PROMISE_FLAG_RESOLVED are set, this promise is fulfilled.
+// If only PROMISE_FLAG_RESOLVED is set, this promise is rejected.
 #define PROMISE_FLAG_FULFILLED 0x2
+
+// Indicates the promise has ever had a fulfillment or rejection handler;
+// used in unhandled rejection tracking.
 #define PROMISE_FLAG_HANDLED   0x4
+
+// This promise uses the default resolving functions.
+// The PromiseSlot_RejectFunction slot is not used.
 #define PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS 0x08
+
+// This promise is the return value of an async function invocation.
 #define PROMISE_FLAG_ASYNC    0x10
 
 class AutoSetNewObjectMetadata;
 
 class PromiseObject : public NativeObject
 {
   public:
     static const unsigned RESERVED_SLOTS = PromiseSlots;
@@ -87,17 +122,20 @@ class PromiseObject : public NativeObjec
     JSObject* allocationSite();
     JSObject* resolutionSite();
     double lifetime();
     double timeToResolution() {
         MOZ_ASSERT(state() != JS::PromiseState::Pending);
         return resolutionTime() - allocationTime();
     }
     MOZ_MUST_USE bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values);
+
+    // Return the process-unique ID of this promise. Only used by the debugger.
     uint64_t getID();
+
     bool isUnhandled() {
         MOZ_ASSERT(state() == JS::PromiseState::Rejected);
         return !(flags() & PROMISE_FLAG_HANDLED);
     }
 };
 
 /**
  * Unforgeable version of the JS builtin Promise.all.
@@ -108,19 +146,28 @@ class PromiseObject : public NativeObjec
  * promise.
  *
  * Asserts that all objects in the `promises` vector are, maybe wrapped,
  * instances of `Promise` or a subclass of `Promise`.
  */
 MOZ_MUST_USE JSObject*
 GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises);
 
+// Whether to create a promise as the return value of Promise#{then,catch}.
+// If the return value is known to be unused, and if the operation is known
+// to be unobservable, we can skip creating the promise.
 enum class CreateDependentPromise {
+    // The return value is not known to be unused.
     Always,
+
+    // The return value is known to be unused.
     SkipIfCtorUnobservable,
+
+    // The return value is known to be unused, and the operation is known
+    // to be unobservable.
     Never
 };
 
 /**
  * Enqueues resolve/reject reactions in the given Promise's reactions lists
  * as though calling the original value of Promise.prototype.then.
  *
  * If the `createDependent` flag is not set, no dependent Promise will be
@@ -139,19 +186,27 @@ OriginalPromiseThen(JSContext* cx, Handl
  *
  * The abstract operation PromiseResolve, given a constructor and a value,
  * returns a new promise resolved with that value.
  */
 MOZ_MUST_USE JSObject*
 PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
 
 
+/**
+ * Create the promise object which will be used as the return value of an async
+ * function.
+ */
 MOZ_MUST_USE PromiseObject*
 CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal);
 
+/**
+ * Returns true if the given object is a promise created by
+ * CreatePromiseObjectForAsync function.
+ */
 MOZ_MUST_USE bool
 IsPromiseForAsync(JSObject* promise);
 
 MOZ_MUST_USE bool
 AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
 
 MOZ_MUST_USE bool
 AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise);
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -27,16 +27,17 @@
 #include "frontend/ParseNode-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using JS::AutoStableStringChars;
 using JS::AutoValueArray;
+using JS::CompileOptions;
 using mozilla::DebugOnly;
 
 enum ASTType {
     AST_ERROR = -1,
 #define ASTDEF(ast, str, method) ast,
 #include "jsast.tbl"
 #undef ASTDEF
     AST_LIMIT
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -22,16 +22,18 @@
 #include "vm/NativeObject-inl.h"
 #include "vm/UnboxedObject-inl.h"
 
 using namespace js;
 
 using mozilla::CheckedInt;
 using mozilla::IsAsciiDigit;
 
+using JS::CompileOptions;
+
 /*
  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
  * steps 3, 16-25.
  */
 bool
 js::CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches,
                             MutableHandleValue rval)
 {
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -37,19 +37,22 @@
 #include "irregexp/RegExpEngine.h"
 #include "irregexp/RegExpParser.h"
 #endif
 #include "gc/Heap.h"
 #include "jit/BaselineJIT.h"
 #include "jit/InlinableNatives.h"
 #include "jit/JitRealm.h"
 #include "js/AutoByteString.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/CompileOptions.h"
 #include "js/Debug.h"
 #include "js/HashTable.h"
 #include "js/LocaleSensitive.h"
+#include "js/SourceBufferHolder.h"
 #include "js/StableStringChars.h"
 #include "js/StructuredClone.h"
 #include "js/UbiNode.h"
 #include "js/UbiNodeBreadthFirst.h"
 #include "js/UbiNodeShortestPaths.h"
 #include "js/UniquePtr.h"
 #include "js/Vector.h"
 #include "js/Wrapper.h"
@@ -84,16 +87,18 @@
 #include "vm/StringType-inl.h"
 
 using namespace js;
 
 using mozilla::ArrayLength;
 using mozilla::Maybe;
 
 using JS::AutoStableStringChars;
+using JS::CompileOptions;
+using JS::SourceBufferHolder;
 
 // If fuzzingSafe is set, remove functionality that could cause problems with
 // fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
 mozilla::Atomic<bool> fuzzingSafe(false);
 
 // If disableOOMFunctions is set, disable functionality that causes artificial
 // OOM conditions.
 static mozilla::Atomic<bool> disableOOMFunctions(false);
--- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
+++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
@@ -433,17 +433,17 @@ function ignoreContents(entry)
         // These ought to be threadsafe.
         "NS_DebugBreak",
         /mozalloc_handle_oom/,
         /^NS_Log/, /log_print/, /LazyLogModule::operator/,
         /SprintfLiteral/, "PR_smprintf", "PR_smprintf_free",
         /NS_DispatchToMainThread/, /NS_ReleaseOnMainThreadSystemGroup/,
         /NS_NewRunnableFunction/, /NS_Atomize/,
         /nsCSSValue::BufferFromString/,
-        /NS_strdup/,
+        /NS_xstrdup/,
         /Assert_NoQueryNeeded/,
         /AssertCurrentThreadOwnsMe/,
         /PlatformThread::CurrentId/,
         /imgRequestProxy::GetProgressTracker/, // Uses an AutoLock
         /Smprintf/,
         "malloc",
         "calloc",
         "free",
--- a/js/src/frontend/BinSource.h
+++ b/js/src/frontend/BinSource.h
@@ -20,16 +20,17 @@
 #include "frontend/BinToken.h"
 #include "frontend/BinTokenReaderMultipart.h"
 #include "frontend/BinTokenReaderTester.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/ParseContext.h"
 #include "frontend/ParseNode.h"
 #include "frontend/SharedContext.h"
 
+#include "js/CompileOptions.h"
 #include "js/GCHashTable.h"
 #include "js/GCVector.h"
 #include "js/Result.h"
 
 namespace js {
 namespace frontend {
 
 class BinASTParserBase: private JS::AutoGCRooter
@@ -182,19 +183,19 @@ class BinASTParser : public BinASTParser
     MOZ_MUST_USE JS::Result<Ok> checkFunctionClosedVars();
 
     // --- Utilities.
 
     MOZ_MUST_USE JS::Result<ParseNode*> appendDirectivesToBody(ParseNode* body,
         ParseNode* directives);
 
   private: // Implement ErrorReporter
-    const ReadOnlyCompileOptions& options_;
+    const JS::ReadOnlyCompileOptions& options_;
 
-    const ReadOnlyCompileOptions& options() const override {
+    const JS::ReadOnlyCompileOptions& options() const override {
         return this->options_;
     }
 
   public:
     virtual ObjectBox* newObjectBox(JSObject* obj) override {
         MOZ_ASSERT(obj);
 
         /*
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -12,32 +12,38 @@
 #include "builtin/ModuleObject.h"
 #if defined(JS_BUILD_BINAST)
 # include "frontend/BinSource.h"
 #endif // JS_BUILD_BINAST
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/ErrorReporter.h"
 #include "frontend/FoldConstants.h"
 #include "frontend/Parser.h"
+#include "js/SourceBufferHolder.h"
 #include "vm/GlobalObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSScript.h"
 #include "vm/TraceLogging.h"
 #include "wasm/AsmJS.h"
 
 #include "vm/EnvironmentObject-inl.h"
 #include "vm/GeckoProfiler-inl.h"
 #include "vm/JSObject-inl.h"
 #include "vm/JSScript-inl.h"
 
 using namespace js;
 using namespace js::frontend;
+
 using mozilla::Maybe;
 using mozilla::Nothing;
 
+using JS::CompileOptions;
+using JS::ReadOnlyCompileOptions;
+using JS::SourceBufferHolder;
+
 // The BytecodeCompiler class contains resources common to compiling scripts and
 // function bodies.
 class MOZ_STACK_CLASS BytecodeCompiler
 {
   public:
     // Construct an object passing mandatory arguments.
     BytecodeCompiler(JSContext* cx,
                      LifoAlloc& alloc,
@@ -703,17 +709,17 @@ frontend::CompileModule(JSContext* cx, c
     if (!script)
         return nullptr;
 
     assertException.reset();
     return script;
 }
 
 JSScript*
-frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+frontend::CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
                         SourceBufferHolder& srcBuf)
 {
     AutoAssertReportedException assertException(cx);
 
     if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
         return nullptr;
 
     LifoAlloc& alloc = cx->tempLifoAlloc();
@@ -781,17 +787,17 @@ frontend::CompileLazyFunction(JSContext*
     // compiled, because compilation requires full information about the
     // function's immediately enclosing scope.
     MOZ_ASSERT(lazy->enclosingScriptHasEverBeenCompiled());
 
     AutoAssertReportedException assertException(cx);
     Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
     AutoAssertFunctionDelazificationCompletion delazificationCompletion(cx, fun);
 
-    CompileOptions options(cx);
+    JS::CompileOptions options(cx);
     options.setMutedErrors(lazy->mutedErrors())
            .setFileAndLine(lazy->filename(), lazy->lineno())
            .setColumn(lazy->column())
            .setScriptSourceOffset(lazy->sourceStart())
            .setNoScriptRval(false)
            .setSelfHostingMode(false);
 
     // Update statistics to find out if we are delazifying just after having
@@ -848,17 +854,17 @@ frontend::CompileLazyFunction(JSContext*
 
     delazificationCompletion.complete();
     assertException.reset();
     return true;
 }
 
 bool
 frontend::CompileStandaloneFunction(JSContext* cx, MutableHandleFunction fun,
-                                    const ReadOnlyCompileOptions& options,
+                                    const JS::ReadOnlyCompileOptions& options,
                                     JS::SourceBufferHolder& srcBuf,
                                     const Maybe<uint32_t>& parameterListEnd,
                                     HandleScope enclosingScope /* = nullptr */)
 {
     AutoAssertReportedException assertException(cx);
 
     RootedScope scope(cx, enclosingScope);
     if (!scope)
@@ -873,17 +879,17 @@ frontend::CompileStandaloneFunction(JSCo
     }
 
     assertException.reset();
     return true;
 }
 
 bool
 frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun,
-                                     const ReadOnlyCompileOptions& options,
+                                     const JS::ReadOnlyCompileOptions& options,
                                      JS::SourceBufferHolder& srcBuf,
                                      const Maybe<uint32_t>& parameterListEnd)
 {
     AutoAssertReportedException assertException(cx);
 
     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
 
     BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -6,16 +6,17 @@
 
 #ifndef frontend_BytecodeCompiler_h
 #define frontend_BytecodeCompiler_h
 
 #include "mozilla/Maybe.h"
 
 #include "NamespaceImports.h"
 
+#include "js/CompileOptions.h"
 #include "vm/Scope.h"
 #include "vm/StringType.h"
 #include "vm/TraceLogging.h"
 
 class JSLinearString;
 
 namespace js {
 
@@ -26,44 +27,44 @@ class ScriptSourceObject;
 namespace frontend {
 
 class ErrorReporter;
 class FunctionBox;
 class ParseNode;
 
 JSScript*
 CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
-                    const ReadOnlyCompileOptions& options,
-                    SourceBufferHolder& srcBuf,
+                    const JS::ReadOnlyCompileOptions& options,
+                    JS::SourceBufferHolder& srcBuf,
                     ScriptSourceObject** sourceObjectOut = nullptr);
 
 #if defined(JS_BUILD_BINAST)
 
 JSScript*
 CompileGlobalBinASTScript(JSContext *cx, LifoAlloc& alloc,
-                          const ReadOnlyCompileOptions& options,
+                          const JS::ReadOnlyCompileOptions& options,
                           const uint8_t* src, size_t len,
                           ScriptSourceObject** sourceObjectOut = nullptr);
 
 #endif // JS_BUILD_BINAST
 
 JSScript*
 CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
                   HandleObject scopeChain, HandleScope enclosingScope,
-                  const ReadOnlyCompileOptions& options,
-                  SourceBufferHolder& srcBuf,
+                  const JS::ReadOnlyCompileOptions& o