Merge inbound to mozilla-central. a=merge
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Thu, 20 Dec 2018 23:56:42 +0200
changeset 451579 a1e34d928bad0031eba642414d97c2407af31ec1
parent 451578 b62196039b0c5f1e0b4a6425cf76b5c1623fe892 (current diff)
parent 451532 9f5cba4d364b2a65cc97820e9bb5e363f90615f3 (diff)
child 451580 eed9325163623930bbd89340275baad218f9d5a1
child 451625 95cbd1c9115a3209a0e66f7c8bc6676fa7550822
push id110693
push usernbeleuzu@mozilla.com
push dateThu, 20 Dec 2018 22:05:28 +0000
treeherdermozilla-inbound@eed932516362 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
a1e34d928bad / 66.0a1 / 20181220215605 / files
nightly linux64
a1e34d928bad / 66.0a1 / 20181220215605 / files
nightly mac
a1e34d928bad / 66.0a1 / 20181220215605 / files
nightly win32
a1e34d928bad / 66.0a1 / 20181220215605 / files
nightly win64
a1e34d928bad / 66.0a1 / 20181220215605 / 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/app/profile/firefox.js
dom/localstorage/ActorsParent.cpp
dom/payments/test/mochitest.ini
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -70,37 +70,37 @@ tasks:
                 - "index.gecko.v2.${repository.project}.revision.${push.revision}.taskgraph.decision"
                 - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision"
                 - "notify.email.${ownerEmail}.on-failed"
                 - "notify.email.${ownerEmail}.on-exception"
                 # Send a notification email if the push comes from try
                 - $if: 'repository.project == "try"'
                   then:
                     "notify.email.${ownerEmail}.on-completed"
-                # BUG 1500166 Notify ciduty by email if a nightly hook fails
-                - "notify.email.ciduty+failedcron@mozilla.com.on-failed"
-                - "notify.email.ciduty+exceptioncron@mozilla.com.on-exception"
-                - "notify.email.sheriffs+failedcron@mozilla.com.on-failed"
-                - "notify.email.sheriffs+exceptioncron@mozilla.com.on-exception"
                 # These are the old index routes for the decision task.
                 # They are still here so external tools that referenced them continue to work.
                 - "index.gecko.v2.${repository.project}.latest.firefox.decision"
                 - "index.gecko.v2.${repository.project}.revision.${push.revision}.firefox.decision"
               else:
                 $if: 'tasks_for == "action"'
                 then:
                 - "notify.email.taskcluster-notifications+action-task@mozilla.com.on-failed"
                 - "notify.email.taskcluster-notifications+action-task@mozilla.com.on-exception"
                 - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.actions.${ownTaskId}"
                 else:  # cron
                 - "index.gecko.v2.${repository.project}.latest.taskgraph.decision-${cron.job_name}"
                 - "index.gecko.v2.${repository.project}.revision.${push.revision}.taskgraph.decision-${cron.job_name}"
                 - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision-${cron.job_name}"
                 # list each cron task on this revision, so actions can find them
                 - 'index.gecko.v2.${repository.project}.revision.${push.revision}.cron.${as_slugid("decision")}'
+                # BUG 1500166 Notify ciduty by email if a nightly hook fails
+                - "notify.email.ciduty+failedcron@mozilla.com.on-failed"
+                - "notify.email.ciduty+exceptioncron@mozilla.com.on-exception"
+                - "notify.email.sheriffs+failedcron@mozilla.org.on-failed"
+                - "notify.email.sheriffs+exceptioncron@mozilla.org.on-exception"
                 # These are the old index routes for the decision task.
                 - "index.gecko.v2.${repository.project}.latest.firefox.decision-${cron.job_name}"
 
         scopes:
           $if: 'tasks_for == "hg-push"'
           then:
             - 'assume:repo:${repoUrl[8:]}:branch:default'
             - 'queue:route:notify.email.${ownerEmail}.*'
@@ -241,9 +241,9 @@ tasks:
               then:
                 notify:
                   email:
                     subject: "Thank you for your try submission of ${push.revision}. It's the best!"
                     content: "Your try push has been submitted. It's the best! Use the link to view the status of your jobs."
                     link:
                       text: "Treeherder Jobs"
                       href: "https://treeherder.mozilla.org/#/jobs?repo=${repository.project}&revision=${push.revision}"
-          
+
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1510,18 +1510,21 @@ pref("toolkit.telemetry.hybridContent.en
 pref("browser.ping-centre.telemetry", true);
 pref("browser.ping-centre.log", false);
 pref("browser.ping-centre.staging.endpoint", "https://onyx_tiles.stage.mozaws.net/v3/links/ping-centre");
 pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.com/v3/links/ping-centre");
 
 // Enable GMP support in the addon manager.
 pref("media.gmp-provider.enabled", true);
 
-// Enable blocking access to storage from tracking resources by default
+// Enable blocking access to storage from tracking resources only in nightly
+// and early beta. By default the value is 0: BEHAVIOR_ACCEPT
+#ifdef NIGHTLY_OR_EARLY_BETA
 pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
+#endif
 
 pref("browser.contentblocking.allowlist.storage.enabled", true);
 
 #ifdef NIGHTLY_BUILD
 // Enable the Storage Access API in Nightly
 pref("dom.storage_access.enabled", true);
 #endif
 
--- a/browser/components/payments/res/components/rich-select.js
+++ b/browser/components/payments/res/components/rich-select.js
@@ -1,24 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 import ObservedPropertiesMixin from "../mixins/ObservedPropertiesMixin.js";
 import RichOption from "./rich-option.js";
 
 /**
  * <rich-select>
  *  <rich-option></rich-option>
  * </rich-select>
  *
  * Note: The only supported way to change the selected option is via the
  *       `value` setter.
  */
-export default class RichSelect extends ObservedPropertiesMixin(HTMLElement) {
+export default class RichSelect extends HandleEventMixin(ObservedPropertiesMixin(HTMLElement)) {
   static get observedAttributes() {
     return [
       "disabled",
       "hidden",
     ];
   }
 
   constructor() {
@@ -52,25 +53,20 @@ export default class RichSelect extends 
     this.popupBox.value = guid;
     this.render();
   }
 
   getOptionByValue(value) {
     return this.popupBox.querySelector(`:scope > [value="${CSS.escape(value)}"]`);
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "change": {
-        // Since the render function depends on the popupBox's value, we need to
-        // re-render if the value changes.
-        this.render();
-        break;
-      }
-    }
+  onChange(event) {
+    // Since the render function depends on the popupBox's value, we need to
+    // re-render if the value changes.
+    this.render();
   }
 
   render() {
     let selectedRichOption = this.querySelector(":scope > .rich-select-selected-option");
     if (selectedRichOption) {
       selectedRichOption.remove();
     }
 
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -2,30 +2,32 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* import-globals-from ../../../../../browser/extensions/formautofill/content/autofillEditForms.js*/
 import LabelledCheckbox from "../components/labelled-checkbox.js";
 import PaymentRequestPage from "../components/payment-request-page.js";
 import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
 import paymentRequest from "../paymentRequest.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 /* import-globals-from ../unprivileged-fallbacks.js */
 
 /**
  * <address-form></address-form>
  *
  * Don't use document.getElementById or document.querySelector* to access form
  * elements, use querySelector on `this` or `this.form` instead so that elements
  * can be found before the element is connected.
  *
  * XXX: Bug 1446164 - This form isn't localized when used via this custom element
  * as it will be much easier to share the logic once we switch to Fluent.
  */
 
-export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequestPage) {
+export default class AddressForm extends
+    HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
   constructor() {
     super();
 
     this.genericErrorText = document.createElement("div");
     this.genericErrorText.setAttribute("aria-live", "polite");
     this.genericErrorText.classList.add("page-error");
 
     this.cancelButton = document.createElement("button");
@@ -211,42 +213,28 @@ export default class AddressForm extends
       field.setCustomValidity(errorText);
       let span = paymentRequest.maybeCreateFieldErrorElement(container);
       span.textContent = errorText;
     }
 
     this.updateSaveButtonState();
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "change": {
-        if (event.target.id == "country") {
-          this.updateRequiredState();
-        }
-        this.updateSaveButtonState();
-        break;
-      }
-      case "click": {
-        this.onClick(event);
-        break;
-      }
-      case "input": {
-        this.onInput(event);
-        break;
-      }
-      case "invalid": {
-        if (event.target instanceof HTMLFormElement) {
-          this.onInvalidForm(event);
-          break;
-        }
+  onChange(event) {
+    if (event.target.id == "country") {
+      this.updateRequiredState();
+    }
+    this.updateSaveButtonState();
+  }
 
-        this.onInvalidField(event);
-        break;
-      }
+  onInvalid(event) {
+    if (event.target instanceof HTMLFormElement) {
+      this.onInvalidForm(event);
+    } else {
+      this.onInvalidField(event);
     }
   }
 
   onClick(evt) {
     switch (evt.target) {
       case this.cancelButton: {
         paymentRequest.cancel();
         break;
--- a/browser/components/payments/res/containers/address-picker.js
+++ b/browser/components/payments/res/containers/address-picker.js
@@ -1,24 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 import AddressForm from "./address-form.js";
 import AddressOption from "../components/address-option.js";
 import RichPicker from "./rich-picker.js";
 import paymentRequest from "../paymentRequest.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 
 /**
  * <address-picker></address-picker>
  * Container around add/edit links and <rich-select> with
  * <address-option> listening to savedAddresses & tempAddresses.
  */
 
-export default class AddressPicker extends RichPicker {
+export default class AddressPicker extends HandleEventMixin(RichPicker) {
   static get pickerAttributes() {
     return [
       "address-fields",
       "break-after-nth-field",
       "data-field-separator",
     ];
   }
 
@@ -192,28 +193,16 @@ export default class AddressPicker exten
     let merchantFieldErrors = AddressForm.merchantFieldErrorsForForm(
           state, this.selectedStateKey.split("|"));
     // TODO: errors in priority order.
     return Object.values(merchantFieldErrors).find(msg => {
       return typeof(msg) == "string" && msg.length;
     }) || "";
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "change": {
-        this.onChange(event);
-        break;
-      }
-      case "click": {
-        this.onClick(event);
-      }
-    }
-  }
-
   onChange(event) {
     let [selectedKey, selectedLeaf] = this.selectedStateKey.split("|");
     if (!selectedKey) {
       return;
     }
     // selectedStateKey can be a '|' delimited string indicating a path into the state object
     // to update with the new value
     let newState = {};
--- a/browser/components/payments/res/containers/basic-card-form.js
+++ b/browser/components/payments/res/containers/basic-card-form.js
@@ -5,27 +5,29 @@
 /* import-globals-from ../../../../../browser/extensions/formautofill/content/autofillEditForms.js*/
 import AcceptedCards from "../components/accepted-cards.js";
 import BillingAddressPicker from "./billing-address-picker.js";
 import CscInput from "../components/csc-input.js";
 import LabelledCheckbox from "../components/labelled-checkbox.js";
 import PaymentRequestPage from "../components/payment-request-page.js";
 import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
 import paymentRequest from "../paymentRequest.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 
 /* import-globals-from ../unprivileged-fallbacks.js */
 
 /**
  * <basic-card-form></basic-card-form>
  *
  * XXX: Bug 1446164 - This form isn't localized when used via this custom element
  * as it will be much easier to share the logic once we switch to Fluent.
  */
 
-export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRequestPage) {
+export default class BasicCardForm extends
+    HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
   constructor() {
     super();
 
     this.genericErrorText = document.createElement("div");
     this.genericErrorText.setAttribute("aria-live", "polite");
     this.genericErrorText.classList.add("page-error");
 
     this.cscInput = new CscInput({
@@ -263,42 +265,16 @@ export default class BasicCardForm exten
     // Need to recalculate the populated state since
     // billingAddressSelect is updated after loadRecord.
     this.formHandler.updatePopulatedState(billingAddressSelect.popupBox);
 
     this.updateRequiredState();
     this.updateSaveButtonState();
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "change": {
-        this.onChange(event);
-        break;
-      }
-      case "click": {
-        this.onClick(event);
-        break;
-      }
-      case "input": {
-        this.onInput(event);
-        break;
-      }
-      case "invalid": {
-        if (event.target instanceof HTMLFormElement) {
-          this.onInvalidForm(event);
-          break;
-        }
-
-        this.onInvalidField(event);
-        break;
-      }
-    }
-  }
-
   onChange(evt) {
     let ccType = this.form.querySelector("#cc-type");
     this.cscInput.setAttribute("card-type", ccType.value);
 
     this.updateSaveButtonState();
   }
 
   onClick(evt) {
@@ -385,16 +361,24 @@ export default class BasicCardForm exten
     }
   }
 
   onInput(event) {
     event.target.setCustomValidity("");
     this.updateSaveButtonState();
   }
 
+  onInvalid(event) {
+    if (event.target instanceof HTMLFormElement) {
+      this.onInvalidForm(event);
+    } else {
+      this.onInvalidField(event);
+    }
+  }
+
   /**
    * @param {Event} event - "invalid" event
    * Note: Keep this in-sync with the equivalent version in address-form.js
    */
   onInvalidField(event) {
     let field = event.target;
     let container = field.closest(`#${field.id}-container`);
     let errorTextSpan = paymentRequest.maybeCreateFieldErrorElement(container);
--- a/browser/components/payments/res/containers/completion-error-page.js
+++ b/browser/components/payments/res/containers/completion-error-page.js
@@ -1,26 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 import PaymentRequestPage from "../components/payment-request-page.js";
 import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
 import paymentRequest from "../paymentRequest.js";
 
 /* import-globals-from ../unprivileged-fallbacks.js */
 
 /**
  * <completion-error-page></completion-error-page>
  *
  * XXX: Bug 1473772 - This page isn't fully localized when used via this custom element
  * as it will be much easier to implement and share the logic once we switch to Fluent.
  */
 
-export default class CompletionErrorPage extends PaymentStateSubscriberMixin(PaymentRequestPage) {
+export default class CompletionErrorPage extends
+    HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
   constructor() {
     super();
 
     this.classList.add("error-page");
     this.suggestionHeading = document.createElement("p");
     this.body.append(this.suggestionHeading);
     this.suggestionsList = document.createElement("ul");
     this.suggestions = [];
@@ -75,26 +77,24 @@ export default class CompletionErrorPage
     for (let suggestionText of this.suggestions) {
       let listNode = document.createElement("li");
       listNode.textContent = suggestionText;
       suggestionsFragment.appendChild(listNode);
     }
     this.suggestionsList.appendChild(suggestionsFragment);
   }
 
-  handleEvent(event) {
-    if (event.type == "click") {
-      switch (event.target) {
-        case this.doneButton: {
-          this.onDoneButtonClick(event);
-          break;
-        }
-        default: {
-          throw new Error("Unexpected click target");
-        }
+  onClick(event) {
+    switch (event.target) {
+      case this.doneButton: {
+        this.onDoneButtonClick(event);
+        break;
+      }
+      default: {
+        throw new Error("Unexpected click target");
       }
     }
   }
 
   onDoneButtonClick(event) {
     paymentRequest.closeDialog();
   }
 }
--- a/browser/components/payments/res/containers/payment-dialog.js
+++ b/browser/components/payments/res/containers/payment-dialog.js
@@ -1,12 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
 import paymentRequest from "../paymentRequest.js";
 
 import "../components/currency-amount.js";
 import "../components/payment-request-page.js";
 import "../components/accepted-cards.js";
 import "./address-picker.js";
 import "./address-form.js";
@@ -21,17 +22,18 @@ import "./shipping-option-picker.js";
 /**
  * <payment-dialog></payment-dialog>
  *
  * Warning: Do not import this module from any other module as it will import
  * everything else (see above) and ruin element independence. This can stop
  * being exported once tests stop depending on it.
  */
 
-export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLElement) {
+export default class PaymentDialog extends
+    HandleEventMixin(PaymentStateSubscriberMixin(HTMLElement)) {
   constructor() {
     super();
     this._template = document.getElementById("payment-dialog-template");
     this._cachedState = {};
   }
 
   connectedCallback() {
     let contents = document.importNode(this._template.content, true);
@@ -72,32 +74,30 @@ export default class PaymentDialog exten
 
   disconnectedCallback() {
     this._cancelButton.removeEventListener("click", this.cancelRequest);
     this._payButton.removeEventListener("click", this.pay);
     this._viewAllButton.removeEventListener("click", this);
     super.disconnectedCallback();
   }
 
-  handleEvent(event) {
-    if (event.type == "click") {
-      switch (event.currentTarget) {
-        case this._viewAllButton:
-          let orderDetailsShowing = !this.requestStore.getState().orderDetailsShowing;
-          this.requestStore.setState({ orderDetailsShowing });
-          break;
-        case this._payButton:
-          this.pay();
-          break;
-        case this._manageText:
-          if (event.target instanceof HTMLAnchorElement) {
-            this.openPreferences(event);
-          }
-          break;
-      }
+  onClick(event) {
+    switch (event.currentTarget) {
+      case this._viewAllButton:
+        let orderDetailsShowing = !this.requestStore.getState().orderDetailsShowing;
+        this.requestStore.setState({ orderDetailsShowing });
+        break;
+      case this._payButton:
+        this.pay();
+        break;
+      case this._manageText:
+        if (event.target instanceof HTMLAnchorElement) {
+          this.openPreferences(event);
+        }
+        break;
     }
   }
 
   openPreferences(event) {
     paymentRequest.openPreferences();
     event.preventDefault();
   }
 
--- a/browser/components/payments/res/containers/payment-method-picker.js
+++ b/browser/components/payments/res/containers/payment-method-picker.js
@@ -1,25 +1,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 import BasicCardOption from "../components/basic-card-option.js";
 import CscInput from "../components/csc-input.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 import RichPicker from "./rich-picker.js";
 import paymentRequest from "../paymentRequest.js";
+
 /* import-globals-from ../unprivileged-fallbacks.js */
 
 /**
  * <payment-method-picker></payment-method-picker>
  * Container around add/edit links and <rich-select> with
  * <basic-card-option> listening to savedBasicCards.
  */
 
-export default class PaymentMethodPicker extends RichPicker {
+export default class PaymentMethodPicker extends HandleEventMixin(RichPicker) {
   constructor() {
     super();
     this.dropdown.setAttribute("option-type", "basic-card-option");
     this.securityCodeInput = new CscInput();
     this.securityCodeInput.className = "security-code-container";
     this.securityCodeInput.placeholder = this.dataset.cscPlaceholder;
     this.securityCodeInput.backTooltip = this.dataset.cscBackTooltip;
     this.securityCodeInput.frontTooltip = this.dataset.cscFrontTooltip;
@@ -110,28 +112,22 @@ export default class PaymentMethodPicker
                       acceptedNetworks.includes(selectedCard["cc-type"]);
     return isSupported ? "" : this.dataset.invalidLabel;
   }
 
   get selectedStateKey() {
     return this.getAttribute("selected-state-key");
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "input":
-      case "change": {
-        this.onInputOrChange(event);
-        break;
-      }
-      case "click": {
-        this.onClick(event);
-        break;
-      }
-    }
+  onInput(event) {
+    this.onInputOrChange(event);
+  }
+
+  onChange(event) {
+    this.onInputOrChange(event);
   }
 
   onInputOrChange({currentTarget}) {
     let selectedKey = this.selectedStateKey;
     let stateChange = {};
 
     if (!selectedKey) {
       return;
--- a/browser/components/payments/res/containers/shipping-option-picker.js
+++ b/browser/components/payments/res/containers/shipping-option-picker.js
@@ -1,22 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 import RichPicker from "./rich-picker.js";
 import ShippingOption from "../components/shipping-option.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
 
 /**
  * <shipping-option-picker></shipping-option-picker>
  * Container around <rich-select> with
  * <option> listening to shippingOptions.
  */
 
-export default class ShippingOptionPicker extends RichPicker {
+export default class ShippingOptionPicker extends HandleEventMixin(RichPicker) {
   constructor() {
     super();
     this.dropdown.setAttribute("option-type", "shipping-option");
   }
 
   render(state) {
     this.addLink.hidden = true;
     this.editLink.hidden = true;
@@ -50,25 +51,16 @@ export default class ShippingOptionPicke
     this.dropdown.value = selectedShippingOption;
 
     if (selectedShippingOption && selectedShippingOption !== this.dropdown.popupBox.value) {
       throw new Error(`The option ${selectedShippingOption} ` +
                       `does not exist in the shipping option picker`);
     }
   }
 
-  handleEvent(event) {
-    switch (event.type) {
-      case "change": {
-        this.onChange(event);
-        break;
-      }
-    }
-  }
-
   onChange(event) {
     let selectedOptionId = this.dropdown.value;
     this.requestStore.setState({
       selectedShippingOption: selectedOptionId,
     });
   }
 }
 
new file mode 100644
--- /dev/null
+++ b/browser/components/payments/res/mixins/HandleEventMixin.js
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * A mixin to forward events to on* methods if defined.
+ *
+ * @param {string} superclass The class to extend.
+ * @returns {class}
+ */
+export default function HandleEventMixin(superclass) {
+  return class HandleEvent extends superclass {
+    handleEvent(evt) {
+      function capitalize(str) {
+        return str.charAt(0).toUpperCase() + str.slice(1);
+      }
+      if (super.handleEvent) {
+        super.handleEvent(evt);
+      }
+      // Check whether event name is a defined function in object.
+      let fn = "on" + capitalize(evt.type);
+      if (this[fn] && typeof(this[fn]) === "function") {
+        return this[fn](evt);
+      }
+      return null;
+    }
+  };
+}
--- a/browser/components/preferences/in-content/tests/browser_contentblocking.js
+++ b/browser/components/preferences/in-content/tests/browser_contentblocking.js
@@ -227,17 +227,17 @@ add_task(async function testContentBlock
   await TestUtils.waitForCondition(() => !Services.prefs.prefHasUserValue(TP_PREF));
   is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`);
 
   strictRadioOption.click();
   await TestUtils.waitForCondition(() => Services.prefs.getStringPref(CAT_PREF) == "strict");
 
   // Changing the NCB_PREF should necessarily set CAT_PREF to "custom"
   Services.prefs.setIntPref(NCB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
-  await TestUtils.waitForCondition(() => Services.prefs.prefHasUserValue(NCB_PREF));
+  await TestUtils.waitForCondition(() => !Services.prefs.prefHasUserValue(NCB_PREF));
   is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`);
 
   gBrowser.removeCurrentTab();
 });
 
 function checkControlState(doc, controls, enabled) {
   for (let selector of controls) {
     for (let control of doc.querySelectorAll(selector)) {
--- a/browser/config/mozconfigs/win64-aarch64/common-win64
+++ b/browser/config/mozconfigs/win64-aarch64/common-win64
@@ -1,10 +1,7 @@
 # This file is used by all AArch64 Win64 builds
 
 ac_add_options --target=aarch64-windows-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
-# WebRTC is busted in various ways.
-ac_add_options --disable-webrtc
-
 # Accessibility doesn't work.
 ac_add_options --disable-accessibility
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -4325,16 +4325,19 @@ int64_t Datastore::RequestUpdateUsage(in
   return 0;
 }
 
 bool Datastore::UpdateUsage(int64_t aDelta) {
   AssertIsOnBackgroundThread();
 
   // Check internal LocalStorage origin limit.
   int64_t newUsage = mUsage + aDelta;
+
+  MOZ_ASSERT(newUsage >= 0);
+
   if (newUsage > gOriginLimitKB * 1024) {
     return false;
   }
 
   // Check QuotaManager limits (group and global limit).
   if (IsPersistent()) {
     MOZ_ASSERT(mQuotaObject);
 
@@ -5620,17 +5623,18 @@ nsresult PrepareDatastoreOp::DatabaseWor
     return DatabaseNotAvailable();
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (alreadyExisted) {
     MOZ_ASSERT(gUsages);
-    MOZ_ASSERT(gUsages->Get(mOrigin, &mUsage));
+    DebugOnly<bool> hasUsage = gUsages->Get(mOrigin, &mUsage);
+    MOZ_ASSERT(hasUsage);
   } else {
     MOZ_ASSERT(mUsage == 0);
     InitUsageForOrigin(mOrigin, mUsage);
   }
 
   rv = directoryEntry->GetPath(mDatabaseFilePath);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -6906,16 +6910,18 @@ nsresult QuotaClient::InitOrigin(Persist
     }
 
     int64_t usage;
     rv = GetUsage(connection, /* aArchivedOriginScope */ nullptr, &usage);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
+    MOZ_ASSERT(usage >= 0);
+
     InitUsageForOrigin(aOrigin, usage);
 
     aUsageInfo->AppendToDatabaseUsage(uint64_t(usage));
   }
 
   // Report unknown files, don't fail, just warn.
 
   nsCOMPtr<nsIDirectoryEnumerator> directoryEntries;
@@ -6983,16 +6989,17 @@ nsresult QuotaClient::GetUsageForOrigin(
   MOZ_ASSERT(aUsageInfo);
 
   // We can't open the database at this point, since it can be already used
   // by the connection thread. Use the cached value instead.
 
   if (gUsages) {
     int64_t usage;
     if (gUsages->Get(aOrigin, &usage)) {
+      MOZ_ASSERT(usage >= 0);
       aUsageInfo->AppendToDatabaseUsage(usage);
     }
   }
 
   return NS_OK;
 }
 
 nsresult QuotaClient::AboutToClearOrigins(
new file mode 100644
--- /dev/null
+++ b/dom/localstorage/test/unit/test_usage.js
@@ -0,0 +1,66 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+async function testSteps() {
+  const data = {};
+  data.key = "key1";
+  data.value = "value1";
+  data.usage = data.key.length + data.value.length;
+
+  const principal = getPrincipal("http://example.com");
+
+  info("Setting prefs");
+
+  Services.prefs.setBoolPref("dom.storage.next_gen", true);
+
+  info("Stage 1 - Testing usage after adding item");
+
+  info("Getting storage");
+
+  let storage = getLocalStorage(principal);
+
+  info("Adding item");
+
+  storage.setItem(data.key, data.value);
+
+  info("Resetting origin");
+
+  let request = resetOrigin(principal);
+  await requestFinished(request);
+
+  info("Getting usage");
+
+  request = getOriginUsage(principal);
+  await requestFinished(request);
+
+  is(request.result.usage, data.usage, "Correct usage");
+
+  info("Resetting");
+
+  request = reset();
+  await requestFinished(request);
+
+  info("Stage 2 - Testing usage after removing item");
+
+  info("Getting storage");
+
+  storage = getLocalStorage(principal);
+
+  info("Removing item");
+
+  storage.removeItem(data.key);
+
+  info("Resetting origin");
+
+  request = resetOrigin(principal);
+  await requestFinished(request);
+
+  info("Getting usage");
+
+  request = getOriginUsage(principal);
+  await requestFinished(request);
+
+  is(request.result.usage, 0, "Correct usage");
+}
--- a/dom/localstorage/test/unit/xpcshell.ini
+++ b/dom/localstorage/test/unit/xpcshell.ini
@@ -24,8 +24,9 @@ run-sequentially = this test depends on 
 [test_databaseShadowing_clearOriginsByPrefix1.js]
 run-sequentially = test_databaseShadowing_clearOriginsByPrefix2.js depends on a file produced by this test
 [test_databaseShadowing_clearOriginsByPrefix2.js]
 run-sequentially = this test depends on a file produced by test_databaseShadowing_clearOriginsByPrefix1.js
 [test_eviction.js]
 [test_groupLimit.js]
 [test_migration.js]
 [test_snapshotting.js]
+[test_usage.js]
--- a/dom/payments/test/mochitest.ini
+++ b/dom/payments/test/mochitest.ini
@@ -35,16 +35,17 @@ skip-if = debug # Bug 1507251 - Leak
 skip-if = e10s # Bug 1408250: Don't expose PaymentRequest Constructor in non-e10s
 [test_bug1478740.html]
 [test_bug1490698.html]
 [test_canMakePayment.html]
 run-if = nightly_build # Bug 1390737: Depends on the Nightly-only UI service
 skip-if = debug # Bug 1507251 - Leak
 [test_closePayment.html]
 [test_constructor.html]
+skip-if = (os == "linux") # Bug 1514425
 [test_currency_amount_validation.html]
 skip-if = (verify && debug)
 [test_payerDetails.html]
 [test_payment-request-in-iframe.html]
 [test_pmi_validation.html]
 skip-if = (verify && debug)
 [test_requestShipping.html]
 [test_retryPayment.html]
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -20,17 +20,16 @@ using namespace js;
 using mozilla::RoundUpPow2;
 using mozilla::tl::BitSize;
 
 namespace js {
 namespace detail {
 
 /* static */
 UniquePtr<BumpChunk> BumpChunk::newWithCapacity(size_t size) {
-  MOZ_DIAGNOSTIC_ASSERT(RoundUpPow2(size) == size);
   MOZ_DIAGNOSTIC_ASSERT(size >= sizeof(BumpChunk));
   void* mem = js_malloc(size);
   if (!mem) {
     return nullptr;
   }
 
   UniquePtr<BumpChunk> result(new (mem) BumpChunk(size));
 
@@ -99,113 +98,317 @@ void BumpChunk::setReadWrite() {
 }  // namespace js
 
 void LifoAlloc::reset(size_t defaultChunkSize) {
   MOZ_ASSERT(mozilla::IsPowerOfTwo(defaultChunkSize));
 
   while (!chunks_.empty()) {
     chunks_.popFirst();
   }
+  while (!oversize_.empty()) {
+    chunks_.popFirst();
+  }
   while (!unused_.empty()) {
     unused_.popFirst();
   }
   defaultChunkSize_ = defaultChunkSize;
+  oversizeThreshold_ = defaultChunkSize;
   markCount = 0;
   curSize_ = 0;
+  oversizeSize_ = 0;
 }
 
 void LifoAlloc::freeAll() {
   while (!chunks_.empty()) {
     UniqueBumpChunk bc = chunks_.popFirst();
     decrementCurSize(bc->computedSizeOfIncludingThis());
   }
+  while (!oversize_.empty()) {
+    UniqueBumpChunk bc = oversize_.popFirst();
+    decrementCurSize(bc->computedSizeOfIncludingThis());
+    oversizeSize_ -= bc->computedSizeOfIncludingThis();
+  }
   while (!unused_.empty()) {
     UniqueBumpChunk bc = unused_.popFirst();
     decrementCurSize(bc->computedSizeOfIncludingThis());
   }
 
   // Nb: maintaining curSize_ correctly isn't easy.  Fortunately, this is an
   // excellent sanity check.
   MOZ_ASSERT(curSize_ == 0);
+  MOZ_ASSERT(oversizeSize_ == 0);
+}
+
+// Round at the same page granularity used by malloc.
+static size_t MallocGoodSize(size_t aSize) {
+#if defined(MOZ_MEMORY)
+  return malloc_good_size(aSize);
+#else
+  return aSize;
+#endif
 }
 
-LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n) {
+// Heuristic to choose the size of the next BumpChunk for small allocations.
+// `start` is the size of the first chunk. `used` is the total size of all
+// BumpChunks in this LifoAlloc so far.
+static size_t NextSize(size_t start, size_t used) {
+  // Double the size, up to 1 MB.
+  const size_t mb = 1 * 1024 * 1024;
+  if (used < mb) {
+    return Max(start, used);
+  }
+
+  // After 1 MB, grow more gradually, to waste less memory.
+  // The sequence (in megabytes) begins:
+  // 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, ...
+  return JS_ROUNDUP(used / 8, mb);
+}
+
+LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n,
+                                                           bool oversize) {
   MOZ_ASSERT(fallibleScope_,
              "[OOM] Cannot allocate a new chunk in an infallible scope.");
 
   // Compute the size which should be requested in order to be able to fit |n|
   // bytes in a newly allocated chunk, or default to |defaultChunkSize_|.
 
   size_t minSize;
   if (MOZ_UNLIKELY(!detail::BumpChunk::allocSizeWithRedZone(n, &minSize) ||
                    (minSize & (size_t(1) << (BitSize<size_t>::value - 1))))) {
     return nullptr;
   }
 
+  MOZ_ASSERT(curSize_ >= oversizeSize_);
   const size_t chunkSize =
-      minSize > defaultChunkSize_ ? RoundUpPow2(minSize) : defaultChunkSize_;
+      (oversize || minSize > defaultChunkSize_)
+          ? MallocGoodSize(minSize)
+          : NextSize(defaultChunkSize_, curSize_ - oversizeSize_);
 
   // Create a new BumpChunk, and allocate space for it.
   UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
   if (!result) {
     return nullptr;
   }
   MOZ_ASSERT(result->computedSizeOfIncludingThis() == chunkSize);
   return result;
 }
 
-bool LifoAlloc::getOrCreateChunk(size_t n) {
+LifoAlloc::UniqueBumpChunk LifoAlloc::getOrCreateChunk(size_t n) {
   // Look for existing unused BumpChunks to satisfy the request, and pick the
   // first one which is large enough, and move it into the list of used
   // chunks.
   if (!unused_.empty()) {
     if (unused_.begin()->canAlloc(n)) {
-      chunks_.append(unused_.popFirst());
-      return true;
+      return unused_.popFirst();
     }
 
     BumpChunkList::Iterator e(unused_.end());
     for (BumpChunkList::Iterator i(unused_.begin()); i->next() != e.get();
          ++i) {
       detail::BumpChunk* elem = i->next();
       MOZ_ASSERT(elem->empty());
       if (elem->canAlloc(n)) {
         BumpChunkList temp = unused_.splitAfter(i.get());
-        chunks_.append(temp.popFirst());
+        UniqueBumpChunk newChunk = temp.popFirst();
         unused_.appendAll(std::move(temp));
-        return true;
+        return newChunk;
       }
     }
   }
 
   // Allocate a new BumpChunk with enough space for the next allocation.
-  UniqueBumpChunk newChunk = newChunkWithCapacity(n);
+  UniqueBumpChunk newChunk = newChunkWithCapacity(n, false);
+  if (!newChunk) {
+    return newChunk;
+  }
+  size_t size = newChunk->computedSizeOfIncludingThis();
+  incrementCurSize(size);
+  return newChunk;
+}
+
+void* LifoAlloc::allocImplColdPath(size_t n) {
+  void* result;
+  UniqueBumpChunk newChunk = getOrCreateChunk(n);
+  if (!newChunk) {
+    return nullptr;
+  }
+
+  // Since we just created a large enough chunk, this can't fail.
+  chunks_.append(std::move(newChunk));
+  result = chunks_.last()->tryAlloc(n);
+  MOZ_ASSERT(result);
+  return result;
+}
+
+void* LifoAlloc::allocImplOversize(size_t n) {
+  void* result;
+  UniqueBumpChunk newChunk = newChunkWithCapacity(n, true);
+  if (!newChunk) {
+    return nullptr;
+  }
+  incrementCurSize(newChunk->computedSizeOfIncludingThis());
+  oversizeSize_ += newChunk->computedSizeOfIncludingThis();
+
+  // Since we just created a large enough chunk, this can't fail.
+  oversize_.append(std::move(newChunk));
+  result = oversize_.last()->tryAlloc(n);
+  MOZ_ASSERT(result);
+  return result;
+}
+
+bool LifoAlloc::ensureUnusedApproximateColdPath(size_t n, size_t total) {
+  for (detail::BumpChunk& bc : unused_) {
+    total += bc.unused();
+    if (total >= n) {
+      return true;
+    }
+  }
+
+  UniqueBumpChunk newChunk = newChunkWithCapacity(n, false);
   if (!newChunk) {
     return false;
   }
   size_t size = newChunk->computedSizeOfIncludingThis();
-  chunks_.append(std::move(newChunk));
+  unused_.pushFront(std::move(newChunk));
   incrementCurSize(size);
   return true;
 }
 
+LifoAlloc::Mark LifoAlloc::mark() {
+  markCount++;
+  Mark res;
+  if (!chunks_.empty()) {
+    res.chunk = chunks_.last()->mark();
+  }
+  if (!oversize_.empty()) {
+    res.oversize = oversize_.last()->mark();
+  }
+  return res;
+}
+
+void LifoAlloc::release(Mark mark) {
+  markCount--;
+#ifdef DEBUG
+  auto assertIsContained = [](const detail::BumpChunk::Mark& m,
+                              BumpChunkList& list) {
+    if (m.markedChunk()) {
+      bool contained = false;
+      for (const detail::BumpChunk& chunk : list) {
+        if (&chunk == m.markedChunk() && chunk.contains(m)) {
+          contained = true;
+          break;
+        }
+      }
+      MOZ_ASSERT(contained);
+    }
+  };
+  assertIsContained(mark.chunk, chunks_);
+  assertIsContained(mark.oversize, oversize_);
+#endif
+
+  BumpChunkList released;
+  auto cutAtMark = [&released](const detail::BumpChunk::Mark& m,
+                               BumpChunkList& list) {
+    // Move the blocks which are after the mark to the set released chunks.
+    if (!m.markedChunk()) {
+      released = std::move(list);
+    } else {
+      released = list.splitAfter(m.markedChunk());
+    }
+
+    // Release everything which follows the mark in the last chunk.
+    if (!list.empty()) {
+      list.last()->release(m);
+    }
+  };
+
+  // Release the content of all the blocks which are after the marks, and keep
+  // blocks as unused.
+  cutAtMark(mark.chunk, chunks_);
+  for (detail::BumpChunk& bc : released) {
+    bc.release();
+  }
+  unused_.appendAll(std::move(released));
+
+  // Free the content of all the blocks which are after the marks.
+  cutAtMark(mark.oversize, oversize_);
+  while (!released.empty()) {
+    UniqueBumpChunk bc = released.popFirst();
+    decrementCurSize(bc->computedSizeOfIncludingThis());
+    oversizeSize_ -= bc->computedSizeOfIncludingThis();
+  }
+}
+
+void LifoAlloc::steal(LifoAlloc* other) {
+  MOZ_ASSERT(!other->markCount);
+  MOZ_DIAGNOSTIC_ASSERT(unused_.empty());
+  MOZ_DIAGNOSTIC_ASSERT(chunks_.empty());
+  MOZ_DIAGNOSTIC_ASSERT(oversize_.empty());
+
+  // Copy everything from |other| to |this| except for |peakSize_|, which
+  // requires some care.
+  chunks_ = std::move(other->chunks_);
+  oversize_ = std::move(other->oversize_);
+  unused_ = std::move(other->unused_);
+  markCount = other->markCount;
+  defaultChunkSize_ = other->defaultChunkSize_;
+  oversizeThreshold_ = other->oversizeThreshold_;
+  curSize_ = other->curSize_;
+  peakSize_ = Max(peakSize_, other->peakSize_);
+  oversizeSize_ = other->oversizeSize_;
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+  fallibleScope_ = other->fallibleScope_;
+#endif
+
+  other->reset(defaultChunkSize_);
+}
+
 void LifoAlloc::transferFrom(LifoAlloc* other) {
   MOZ_ASSERT(!markCount);
   MOZ_ASSERT(!other->markCount);
 
   incrementCurSize(other->curSize_);
+  oversizeSize_ += other->oversizeSize_;
   appendUnused(std::move(other->unused_));
   appendUsed(std::move(other->chunks_));
+  oversize_.appendAll(std::move(other->oversize_));
   other->curSize_ = 0;
+  other->oversizeSize_ = 0;
 }
 
 void LifoAlloc::transferUnusedFrom(LifoAlloc* other) {
   MOZ_ASSERT(!markCount);
 
   size_t size = 0;
   for (detail::BumpChunk& bc : other->unused_) {
     size += bc.computedSizeOfIncludingThis();
   }
 
   appendUnused(std::move(other->unused_));
   incrementCurSize(size);
   other->decrementCurSize(size);
 }
+
+#ifdef LIFO_CHUNK_PROTECT
+void LifoAlloc::setReadOnly() {
+  for (detail::BumpChunk& bc : chunks_) {
+    bc.setReadOnly();
+  }
+  for (detail::BumpChunk& bc : oversize_) {
+    bc.setReadOnly();
+  }
+  for (detail::BumpChunk& bc : unused_) {
+    bc.setReadOnly();
+  }
+}
+
+void LifoAlloc::setReadWrite() {
+  for (detail::BumpChunk& bc : chunks_) {
+    bc.setReadWrite();
+  }
+  for (detail::BumpChunk& bc : oversize_) {
+    bc.setReadWrite();
+  }
+  for (detail::BumpChunk& bc : unused_) {
+    bc.setReadWrite();
+  }
+}
+#endif
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -357,18 +357,17 @@ class BumpChunk : public SingleLinkedLis
   // pointer, within a BumpChunk.
   class Mark {
     // Chunk which owns the pointer.
     BumpChunk* chunk_;
     // Recorded of the bump_ pointer of the BumpChunk.
     uint8_t* bump_;
 
     friend class BumpChunk;
-    explicit Mark(BumpChunk* chunk, uint8_t* bump)
-        : chunk_(chunk), bump_(bump) {}
+    Mark(BumpChunk* chunk, uint8_t* bump) : chunk_(chunk), bump_(bump) {}
 
    public:
     Mark() : chunk_(nullptr), bump_(nullptr) {}
 
     BumpChunk* markedChunk() const { return chunk_; }
   };
 
   // Return a mark to be able to unwind future allocations with the release
@@ -492,42 +491,52 @@ inline uint8_t* BumpChunk::begin() { ret
 // LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
 //
 // Note: We leave BumpChunks latent in the set of unused chunks after they've
 // been released to avoid thrashing before a GC.
 class LifoAlloc {
   using UniqueBumpChunk = js::UniquePtr<detail::BumpChunk>;
   using BumpChunkList = detail::SingleLinkedList<detail::BumpChunk>;
 
-  // List of chunks containing allocated data. In the common case, the last
-  // chunk of this list is always used to perform the allocations. When the
-  // allocation cannot be performed, we move a Chunk from the unused set to
-  // the list of used chunks.
+  // List of chunks containing allocated data of size smaller than the default
+  // chunk size. In the common case, the last chunk of this list is always
+  // used to perform the allocations. When the allocation cannot be performed,
+  // we move a Chunk from the unused set to the list of used chunks.
   BumpChunkList chunks_;
 
+  // List of chunks containing allocated data where each allocation is larger
+  // than the oversize threshold. Each chunk contains exactly on allocation.
+  // This reduces wasted space in the normal chunk list.
+  //
+  // Oversize chunks are allocated on demand and freed as soon as they are
+  // released, instead of being pushed to the unused list.
+  BumpChunkList oversize_;
+
   // Set of unused chunks, which can be reused for future allocations.
   BumpChunkList unused_;
 
   size_t markCount;
   size_t defaultChunkSize_;
+  size_t oversizeThreshold_;
   size_t curSize_;
   size_t peakSize_;
+  size_t oversizeSize_;
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
   bool fallibleScope_;
 #endif
 
   void operator=(const LifoAlloc&) = delete;
   LifoAlloc(const LifoAlloc&) = delete;
 
   // Return a BumpChunk that can perform an allocation of at least size |n|.
-  UniqueBumpChunk newChunkWithCapacity(size_t n);
+  UniqueBumpChunk newChunkWithCapacity(size_t n, bool oversize);
 
   // Reuse or allocate a BumpChunk that can perform an allocation of at least
   // size |n|, if successful it is placed at the end the list of |chunks_|.
-  MOZ_MUST_USE bool getOrCreateChunk(size_t n);
+  UniqueBumpChunk getOrCreateChunk(size_t n);
 
   void reset(size_t defaultChunkSize);
 
   // Append unused chunks to the end of this LifoAlloc.
   void appendUnused(BumpChunkList&& otherUnused) {
 #ifdef DEBUG
     for (detail::BumpChunk& bc : otherUnused) {
       MOZ_ASSERT(bc.empty());
@@ -549,64 +558,58 @@ class LifoAlloc {
       peakSize_ = curSize_;
     }
   }
   void decrementCurSize(size_t size) {
     MOZ_ASSERT(curSize_ >= size);
     curSize_ -= size;
   }
 
+  void* allocImplColdPath(size_t n);
+  void* allocImplOversize(size_t n);
+
   MOZ_ALWAYS_INLINE
   void* allocImpl(size_t n) {
     void* result;
-    if (!chunks_.empty() && (result = chunks_.last()->tryAlloc(n))) {
+    // Give oversized allocations their own chunk instead of wasting space
+    // due to fragmentation at the end of normal chunk.
+    if (MOZ_UNLIKELY(n > oversizeThreshold_)) {
+      return allocImplOversize(n);
+    }
+    if (MOZ_LIKELY(!chunks_.empty() &&
+                   (result = chunks_.last()->tryAlloc(n)))) {
       return result;
     }
-
-    if (!getOrCreateChunk(n)) {
-      return nullptr;
-    }
+    return allocImplColdPath(n);
+  }
 
-    // Since we just created a large enough chunk, this can't fail.
-    result = chunks_.last()->tryAlloc(n);
-    MOZ_ASSERT(result);
-    return result;
-  }
+  // Check for space in unused chunks or allocate a new unused chunk.
+  MOZ_MUST_USE bool ensureUnusedApproximateColdPath(size_t n, size_t total);
 
  public:
   explicit LifoAlloc(size_t defaultChunkSize)
       : peakSize_(0)
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
         ,
         fallibleScope_(true)
 #endif
   {
     reset(defaultChunkSize);
   }
 
-  // Steal allocated chunks from |other|.
-  void steal(LifoAlloc* other) {
-    MOZ_ASSERT(!other->markCount);
-    MOZ_DIAGNOSTIC_ASSERT(unused_.empty());
-    MOZ_DIAGNOSTIC_ASSERT(chunks_.empty());
+  // Set the threshold to allocate data in its own chunk outside the space for
+  // small allocations.
+  void disableOversize() { oversizeThreshold_ = SIZE_MAX; }
+  void setOversizeThreshold(size_t oversizeThreshold) {
+    MOZ_ASSERT(oversizeThreshold <= defaultChunkSize_);
+    oversizeThreshold_ = oversizeThreshold;
+  }
 
-    // Copy everything from |other| to |this| except for |peakSize_|, which
-    // requires some care.
-    chunks_ = std::move(other->chunks_);
-    unused_ = std::move(other->unused_);
-    markCount = other->markCount;
-    defaultChunkSize_ = other->defaultChunkSize_;
-    curSize_ = other->curSize_;
-    peakSize_ = Max(peakSize_, other->peakSize_);
-#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
-    fallibleScope_ = other->fallibleScope_;
-#endif
-
-    other->reset(defaultChunkSize_);
-  }
+  // Steal allocated chunks from |other|.
+  void steal(LifoAlloc* other);
 
   // Append all chunks from |other|. They are removed from |other|.
   void transferFrom(LifoAlloc* other);
 
   // Append unused chunks from |other|. They are removed from |other|.
   void transferUnusedFrom(LifoAlloc* other);
 
   ~LifoAlloc() { freeAll(); }
@@ -639,28 +642,28 @@ class LifoAlloc {
   // |needed| unused bytes remaining. Returns nullptr if we can't.
   // This is useful for maintaining our ballast invariants while
   // attempting fallible allocations.
   MOZ_ALWAYS_INLINE
   void* allocEnsureUnused(size_t n, size_t needed) {
     JS_OOM_POSSIBLY_FAIL();
     MOZ_ASSERT(fallibleScope_);
 
-    detail::BumpChunk::Mark m = mark();
+    Mark m = mark();
     void* result = allocImpl(n);
     if (!ensureUnusedApproximate(needed)) {
       release(m);
       return nullptr;
     }
     cancelMark(m);
     return result;
   }
 
   template <typename T, typename... Args>
-  MOZ_ALWAYS_INLINE T* allocInSize(size_t n, Args&&... args) {
+  MOZ_ALWAYS_INLINE T* newWithSize(size_t n, Args&&... args) {
     MOZ_ASSERT(n >= sizeof(T), "must request enough space to store a T");
     static_assert(alignof(T) <= detail::LIFO_ALLOC_ALIGN,
                   "LifoAlloc must provide enough alignment to store T");
     void* ptr = alloc(n);
     if (!ptr) {
       return nullptr;
     }
 
@@ -686,31 +689,17 @@ class LifoAlloc {
     size_t total = 0;
     if (!chunks_.empty()) {
       total += chunks_.last()->unused();
       if (total >= n) {
         return true;
       }
     }
 
-    for (detail::BumpChunk& bc : unused_) {
-      total += bc.unused();
-      if (total >= n) {
-        return true;
-      }
-    }
-
-    UniqueBumpChunk newChunk = newChunkWithCapacity(n);
-    if (!newChunk) {
-      return false;
-    }
-    size_t size = newChunk->computedSizeOfIncludingThis();
-    unused_.pushFront(std::move(newChunk));
-    incrementCurSize(size);
-    return true;
+    return ensureUnusedApproximateColdPath(n, total);
   }
 
   MOZ_ALWAYS_INLINE
   void setAsInfallibleByDefault() {
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     fallibleScope_ = false;
 #endif
   }
@@ -751,97 +740,67 @@ class LifoAlloc {
   T* newArrayUninitialized(size_t count) {
     size_t bytes;
     if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes))) {
       return nullptr;
     }
     return static_cast<T*>(alloc(bytes));
   }
 
-  using Mark = detail::BumpChunk::Mark;
-
-  Mark mark() {
-    markCount++;
-    if (chunks_.empty()) {
-      return Mark();
-    }
-    return chunks_.last()->mark();
-  }
-
-  void release(Mark mark) {
-    markCount--;
-
-    // Move the blocks which are after the mark to the set of unused chunks.
-    BumpChunkList released;
-    if (!mark.markedChunk()) {
-      released = std::move(chunks_);
-    } else {
-      released = chunks_.splitAfter(mark.markedChunk());
-    }
-
-    // Release the content of all the blocks which are after the marks.
-    for (detail::BumpChunk& bc : released) {
-      bc.release();
-    }
-    unused_.appendAll(std::move(released));
-
-    // Release everything which follows the mark in the last chunk.
-    if (!chunks_.empty()) {
-      chunks_.last()->release(mark);
-    }
-  }
+  class Mark {
+    friend class LifoAlloc;
+    detail::BumpChunk::Mark chunk;
+    detail::BumpChunk::Mark oversize;
+  };
+  Mark mark();
+  void release(Mark mark);
 
  private:
   void cancelMark(Mark mark) { markCount--; }
 
  public:
   void releaseAll() {
     MOZ_ASSERT(!markCount);
     for (detail::BumpChunk& bc : chunks_) {
       bc.release();
     }
     unused_.appendAll(std::move(chunks_));
+    // On release, we free any oversize allocations instead of keeping them
+    // in unused chunks.
+    while (!oversize_.empty()) {
+      UniqueBumpChunk bc = oversize_.popFirst();
+      decrementCurSize(bc->computedSizeOfIncludingThis());
+      oversizeSize_ -= bc->computedSizeOfIncludingThis();
+    }
   }
 
   // Protect the content of the LifoAlloc chunks.
 #ifdef LIFO_CHUNK_PROTECT
-  void setReadOnly() {
-    for (detail::BumpChunk& bc : chunks_) {
-      bc.setReadOnly();
-    }
-    for (detail::BumpChunk& bc : unused_) {
-      bc.setReadOnly();
-    }
-  }
-  void setReadWrite() {
-    for (detail::BumpChunk& bc : chunks_) {
-      bc.setReadWrite();
-    }
-    for (detail::BumpChunk& bc : unused_) {
-      bc.setReadWrite();
-    }
-  }
+  void setReadOnly();
+  void setReadWrite();
 #else
   void setReadOnly() const {}
   void setReadWrite() const {}
 #endif
 
   // Get the total "used" (occupied bytes) count for the arena chunks.
   size_t used() const {
     size_t accum = 0;
     for (const detail::BumpChunk& chunk : chunks_) {
       accum += chunk.used();
     }
     return accum;
   }
 
   // Return true if the LifoAlloc does not currently contain any allocations.
   bool isEmpty() const {
-    return chunks_.empty() ||
-           (chunks_.begin() == chunks_.last() && chunks_.last()->empty());
+    bool empty = chunks_.empty() ||
+                 (chunks_.begin() == chunks_.last() && chunks_.last()->empty());
+    MOZ_ASSERT_IF(!oversize_.empty(), !oversize_.last()->empty());
+    return empty && oversize_.empty();
   }
 
   // Return the number of bytes remaining to allocate in the current chunk.
   // e.g. How many bytes we can allocate before needing a new block.
   size_t availableInCurrentChunk() const {
     if (chunks_.empty()) {
       return 0;
     }
@@ -849,28 +808,34 @@ class LifoAlloc {
   }
 
   // Get the total size of the arena chunks (including unused space).
   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     size_t n = 0;
     for (const detail::BumpChunk& chunk : chunks_) {
       n += chunk.sizeOfIncludingThis(mallocSizeOf);
     }
+    for (const detail::BumpChunk& chunk : oversize_) {
+      n += chunk.sizeOfIncludingThis(mallocSizeOf);
+    }
     for (const detail::BumpChunk& chunk : unused_) {
       n += chunk.sizeOfIncludingThis(mallocSizeOf);
     }
     return n;
   }
 
   // Get the total size of the arena chunks (including unused space).
   size_t computedSizeOfExcludingThis() const {
     size_t n = 0;
     for (const detail::BumpChunk& chunk : chunks_) {
       n += chunk.computedSizeOfIncludingThis();
     }
+    for (const detail::BumpChunk& chunk : oversize_) {
+      n += chunk.computedSizeOfIncludingThis();
+    }
     for (const detail::BumpChunk& chunk : unused_) {
       n += chunk.computedSizeOfIncludingThis();
     }
     return n;
   }
 
   // Like sizeOfExcludingThis(), but includes the size of the LifoAlloc itself.
   size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
@@ -892,16 +857,21 @@ class LifoAlloc {
 
 #ifdef DEBUG
   bool contains(void* ptr) const {
     for (const detail::BumpChunk& chunk : chunks_) {
       if (chunk.contains(ptr)) {
         return true;
       }
     }
+    for (const detail::BumpChunk& chunk : oversize_) {
+      if (chunk.contains(ptr)) {
+        return true;
+      }
+    }
     return false;
   }
 #endif
 
   // Iterate over the data allocated in a LifoAlloc, and interpret it.
   class Enum {
     friend class LifoAlloc;
     friend class detail::BumpChunk;
@@ -930,16 +900,17 @@ class LifoAlloc {
       return aligned;
     }
 
    public:
     explicit Enum(LifoAlloc& alloc)
         : chunkIt_(alloc.chunks_.begin()),
           chunkEnd_(alloc.chunks_.end()),
           head_(nullptr) {
+      MOZ_RELEASE_ASSERT(alloc.oversize_.empty());
       if (chunkIt_ != chunkEnd_) {
         head_ = chunkIt_->begin();
       }
     }
 
     // Return true if there are no more bytes to enumerate.
     bool empty() {
       return chunkIt_ == chunkEnd_ ||
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1038,17 +1038,17 @@ bool Parser<FullParseHandler, Unit>::che
   return true;
 }
 
 template <typename Scope>
 typename Scope::Data* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc,
                                           uint32_t numBindings) {
   using Data = typename Scope::Data;
   size_t allocSize = SizeOfData<typename Scope::Data>(numBindings);
-  auto* bindings = alloc.allocInSize<Data>(allocSize, numBindings);
+  auto* bindings = alloc.newWithSize<Data>(allocSize, numBindings);
   if (!bindings) {
     ReportOutOfMemory(cx);
   }
   return bindings;
 }
 
 namespace detail {
 
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -143,16 +143,22 @@ class StoreBuffer {
 
     WholeCellBuffer() : storage_(nullptr), head_(nullptr) {}
     ~WholeCellBuffer() { js_delete(storage_); }
 
     MOZ_MUST_USE bool init() {
       MOZ_ASSERT(!head_);
       if (!storage_) {
         storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
+        // This prevents LifoAlloc::Enum from crashing with a release
+        // assertion if we ever allocate one entry larger than
+        // LifoAllocBlockSize.
+        if (storage_) {
+          storage_->disableOversize();
+        }
       }
       clear();
       return bool(storage_);
     }
 
     void clear();
 
     bool isAboutToOverflow() const {
--- a/js/src/jit-test/tests/basic/consume-interpreter-stack-bug1473289.js
+++ b/js/src/jit-test/tests/basic/consume-interpreter-stack-bug1473289.js
@@ -1,9 +1,9 @@
-// |jit-test| allow-overrecursed
+// |jit-test| slow; allow-overrecursed
 
 (function f(x) {
     f(x - 1);
     Array.prototype.unshift.call(a1, s2, a1, t2, a0, p2, t2);
     var r2;
     var r3;
     var r4;
     var r5;
--- a/media/webrtc/trunk/webrtc/common_audio/fir_filter_neon.cc
+++ b/media/webrtc/trunk/webrtc/common_audio/fir_filter_neon.cc
@@ -5,17 +5,21 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "common_audio/fir_filter_neon.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 #include <string.h>
 
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/aligned_malloc.h"
 
 namespace webrtc {
 
 FIRFilterNEON::~FIRFilterNEON() {
--- a/media/webrtc/trunk/webrtc/common_audio/resampler/sinc_resampler_neon.cc
+++ b/media/webrtc/trunk/webrtc/common_audio/resampler/sinc_resampler_neon.cc
@@ -8,17 +8,21 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 // Modified from the Chromium original:
 // src/media/base/sinc_resampler.cc
 
 #include "common_audio/resampler/sinc_resampler.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 namespace webrtc {
 
 float SincResampler::Convolve_NEON(const float* input_ptr, const float* k1,
                                    const float* k2,
                                    double kernel_interpolation_factor) {
   float32x4_t m_input;
   float32x4_t m_sums1 = vmovq_n_f32(0);
--- a/media/webrtc/trunk/webrtc/common_audio/signal_processing/cross_correlation_neon.c
+++ b/media/webrtc/trunk/webrtc/common_audio/signal_processing/cross_correlation_neon.c
@@ -5,17 +5,21 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 static inline void DotProductWithScaleNeon(int32_t* cross_correlation,
                                            const int16_t* vector1,
                                            const int16_t* vector2,
                                            size_t length,
                                            int scaling) {
   size_t i = 0;
   size_t len1 = length >> 3;
@@ -46,17 +50,17 @@ static inline void DotProductWithScaleNe
   int64_t sum_res = 0;
   for (i = len2; i > 0; i -= 1) {
     sum_res += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
     vector1++;
     vector2++;
   }
 
   sum0 = vaddq_s64(sum0, sum1);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   int64_t sum2 = vaddvq_s64(sum0);
   *cross_correlation = (int32_t)((sum2 + sum_res) >> scaling);
 #else
   int64x1_t shift = vdup_n_s64(-scaling);
   int64x1_t sum2 = vadd_s64(vget_low_s64(sum0), vget_high_s64(sum0));
   sum2 = vadd_s64(sum2, vdup_n_s64(sum_res));
   sum2 = vshl_s64(sum2, shift);
   vst1_lane_s32(cross_correlation, vreinterpret_s32_s64(sum2), 0);
--- a/media/webrtc/trunk/webrtc/common_audio/signal_processing/downsample_fast_neon.c
+++ b/media/webrtc/trunk/webrtc/common_audio/signal_processing/downsample_fast_neon.c
@@ -5,17 +5,21 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 // NEON intrinsics version of WebRtcSpl_DownsampleFast()
 // for ARM 32-bit/64-bit platforms.
 int WebRtcSpl_DownsampleFastNeon(const int16_t* data_in,
                                  size_t data_in_length,
                                  int16_t* data_out,
                                  size_t data_out_length,
                                  const int16_t* __restrict coefficients,
--- a/media/webrtc/trunk/webrtc/common_audio/signal_processing/min_max_operations_neon.c
+++ b/media/webrtc/trunk/webrtc/common_audio/signal_processing/min_max_operations_neon.c
@@ -3,17 +3,21 @@
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 #include <stdlib.h>
 
 #include "rtc_base/checks.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 
 // Maximum absolute value of word16 vector. C version for generic platforms.
 int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length) {
   int absolute = 0, maximum = 0;
@@ -32,17 +36,17 @@ int16_t WebRtcSpl_MaxAbsValueW16Neon(con
     v = vld1q_s16(p_start);
     // Note vabs doesn't change the value of -32768.
     v = vabsq_s16(v);
     // Use u16 so we don't lose the value -32768.
     max_qv = vmaxq_u16(max_qv, vreinterpretq_u16_s16(v));
     p_start += 8;
   }
 
-#ifdef WEBRTC_ARCH_ARM64
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   maximum = (int)vmaxvq_u16(max_qv);
 #else
   uint16x4_t max_dv;
   max_dv = vmax_u16(vget_low_u16(max_qv), vget_high_u16(max_qv));
   max_dv = vpmax_u16(max_dv, max_dv);
   max_dv = vpmax_u16(max_dv, max_dv);
 
   maximum = (int)vget_lane_u16(max_dv, 0);
@@ -92,17 +96,17 @@ int32_t WebRtcSpl_MaxAbsValueW32Neon(con
     in32x4_1 = vabsq_s32(in32x4_1);
     // vabs doesn't change the value of 0x80000000.
     // Use u32 so we don't lose the value 0x80000000.
     max32x4_0 = vmaxq_u32(max32x4_0, vreinterpretq_u32_s32(in32x4_0));
     max32x4_1 = vmaxq_u32(max32x4_1, vreinterpretq_u32_s32(in32x4_1));
   }
 
   uint32x4_t max32x4 = vmaxq_u32(max32x4_0, max32x4_1);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   maximum = vmaxvq_u32(max32x4);
 #else
   uint32x2_t max32x2 = vmax_u32(vget_low_u32(max32x4), vget_high_u32(max32x4));
   max32x2 = vpmax_u32(max32x2, max32x2);
 
   maximum = vget_lane_u32(max32x2, 0);
 #endif
 
@@ -135,17 +139,17 @@ int16_t WebRtcSpl_MaxValueW16Neon(const 
 
   // First part, unroll the loop 8 times.
   for (i = 0; i < length - residual; i += 8) {
     int16x8_t in16x8 = vld1q_s16(p_start);
     max16x8 = vmaxq_s16(max16x8, in16x8);
     p_start += 8;
   }
 
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   maximum = vmaxvq_s16(max16x8);
 #else
   int16x4_t max16x4 = vmax_s16(vget_low_s16(max16x8), vget_high_s16(max16x8));
   max16x4 = vpmax_s16(max16x4, max16x4);
   max16x4 = vpmax_s16(max16x4, max16x4);
 
   maximum = vget_lane_s16(max16x4, 0);
 #endif
@@ -178,17 +182,17 @@ int32_t WebRtcSpl_MaxValueW32Neon(const 
     p_start += 4;
     int32x4_t in32x4_1 = vld1q_s32(p_start);
     p_start += 4;
     max32x4_0 = vmaxq_s32(max32x4_0, in32x4_0);
     max32x4_1 = vmaxq_s32(max32x4_1, in32x4_1);
   }
 
   int32x4_t max32x4 = vmaxq_s32(max32x4_0, max32x4_1);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   maximum = vmaxvq_s32(max32x4);
 #else
   int32x2_t max32x2 = vmax_s32(vget_low_s32(max32x4), vget_high_s32(max32x4));
   max32x2 = vpmax_s32(max32x2, max32x2);
 
   maximum = vget_lane_s32(max32x2, 0);
 #endif
 
@@ -215,17 +219,17 @@ int16_t WebRtcSpl_MinValueW16Neon(const 
 
   // First part, unroll the loop 8 times.
   for (i = 0; i < length - residual; i += 8) {
     int16x8_t in16x8 = vld1q_s16(p_start);
     min16x8 = vminq_s16(min16x8, in16x8);
     p_start += 8;
   }
 
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   minimum = vminvq_s16(min16x8);
 #else
   int16x4_t min16x4 = vmin_s16(vget_low_s16(min16x8), vget_high_s16(min16x8));
   min16x4 = vpmin_s16(min16x4, min16x4);
   min16x4 = vpmin_s16(min16x4, min16x4);
 
   minimum = vget_lane_s16(min16x4, 0);
 #endif
@@ -258,17 +262,17 @@ int32_t WebRtcSpl_MinValueW32Neon(const 
     p_start += 4;
     int32x4_t in32x4_1 = vld1q_s32(p_start);
     p_start += 4;
     min32x4_0 = vminq_s32(min32x4_0, in32x4_0);
     min32x4_1 = vminq_s32(min32x4_1, in32x4_1);
   }
 
   int32x4_t min32x4 = vminq_s32(min32x4_0, min32x4_1);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   minimum = vminvq_s32(min32x4);
 #else
   int32x2_t min32x2 = vmin_s32(vget_low_s32(min32x4), vget_high_s32(min32x4));
   min32x2 = vpmin_s32(min32x2, min32x2);
 
   minimum = vget_lane_s32(min32x2, 0);
 #endif
 
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
@@ -11,17 +11,21 @@
 /* This file contains WebRtcIsacfix_MatrixProduct1Neon() and
  * WebRtcIsacfix_MatrixProduct2Neon() for ARM Neon platform. API's are in
  * entropy_coding.c. Results are bit exact with the c code for
  * generic platforms.
  */
 
 #include "entropy_coding.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 #include <stddef.h>
 
 #include "signal_processing_library.h"
 #include "rtc_base/checks.h"
 
 void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
                                       const int32_t matrix1[],
                                       int32_t matrix_product[],
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
@@ -8,17 +8,21 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 // Contains a function for WebRtcIsacfix_AllpassFilter2FixDec16Neon()
 // in iSAC codec, optimized for ARM Neon platform. Bit exact with function
 // WebRtcIsacfix_AllpassFilter2FixDec16C() in filterbanks.c. Prototype
 // C code is at end of this file.
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "rtc_base/checks.h"
 
 void WebRtcIsacfix_AllpassFilter2FixDec16Neon(
     int16_t* data_ch1,  // Input and output in channel 1, in Q0
     int16_t* data_ch2,  // Input and output in channel 2, in Q0
     const int16_t* factor_ch1,  // Scaling factor for channel 1, in Q15
     const int16_t* factor_ch2,  // Scaling factor for channel 2, in Q15
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
@@ -3,17 +3,21 @@
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "rtc_base/checks.h"
 #include "modules/audio_coding/codecs/isac/fix/source/codec.h"
 
 // Autocorrelation function in fixed point.
 // NOTE! Different from SPLIB-version in how it scales the signal.
 int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
                                const int16_t* x,
@@ -39,17 +43,17 @@ int WebRtcIsacfix_AutocorrNeon(int32_t* 
   const int16_t* x_end0 = x_start + n;
   while (x_start < x_end0) {
     x0_v = vld1_s16(x_start);
     tmpa0_v = vmull_s16(x0_v, x0_v);
     tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
     x_start += 4;
   }
 
-#ifdef WEBRTC_ARCH_ARM64
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   prod = vaddvq_s64(tmpb_v);
 #else
   prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
                        0);
 #endif
   // Calculate scaling (the value of shifting).
   temp = (uint32_t)(prod >> 31);
 
@@ -85,17 +89,17 @@ int WebRtcIsacfix_AutocorrNeon(int32_t* 
     if (rest >= 4) {
         int16x4_t x2_v = vld1_s16(x_start);
         int16x4_t y2_v = vld1_s16(y_start);
         tmpa0_v = vmull_s16(x2_v, y2_v);
         tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
         x_start += 4;
         y_start += 4;
     }
-#ifdef WEBRTC_ARCH_ARM64
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
     prod = vaddvq_s64(tmpb_v);
 #else
     prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
                          0);
 #endif
 
     prod_tail = 0;
     while (x_start < x_end1) {
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
@@ -3,17 +3,21 @@
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "modules/audio_coding/codecs/isac/fix/source/codec.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
 
 // Contains a function for the core loop in the normalized lattice MA
 // filter routine for iSAC codec, optimized for ARM Neon platform.
 // It does:
 //  for 0 <= n < HALF_SUBFRAMELEN - 1:
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
@@ -6,18 +6,22 @@
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
 
 #ifdef WEBRTC_HAS_NEON
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
 #endif
+#endif
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "rtc_base/compile_assert_c.h"
 
 extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
 
 void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
   int16_t scaling,n,k;
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
@@ -3,17 +3,21 @@
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "modules/audio_coding/codecs/isac/fix/source/codec.h"
 #include "modules/audio_coding/codecs/isac/fix/source/fft.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
 
 // Tables are defined in transform_tables.c file.
 // Cosine table 1 in Q14.
 extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
@@ -46,17 +50,17 @@ static inline int32_t ComplexMulAndFindM
     inre1Q9 += 8;
     inre2Q9 += 8;
 
     // Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code.
     int32x4_t tmp0 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre1));
     int32x4_t tmp1 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre2));
     tmp0 = vmlal_s16(tmp0, vget_low_s16(tmpi), vget_low_s16(inre2));
     tmp1 = vmlsl_s16(tmp1, vget_low_s16(tmpi), vget_low_s16(inre1));
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
     int32x4_t tmp2 = vmull_high_s16(tmpr, inre1);
     int32x4_t tmp3 = vmull_high_s16(tmpr, inre2);
     tmp2 = vmlal_high_s16(tmp2, tmpi, inre2);
     tmp3 = vmlsl_high_s16(tmp3, tmpi, inre1);
 #else
     int32x4_t tmp2 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre1));
     int32x4_t tmp3 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre2));
     tmp2 = vmlal_s16(tmp2, vget_high_s16(tmpi), vget_high_s16(inre2));
@@ -85,17 +89,17 @@ static inline int32_t ComplexMulAndFindM
     // Use u32 so we don't lose the value 0x80000000.
     max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp0));
     max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp2));
     max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp1));
     max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp3));
   }
 
   max_r = vmaxq_u32(max_r, max_i);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   uint32_t maximum = vmaxvq_u32(max_r);
 #else
   uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
   max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
   uint32_t maximum = vget_lane_u32(max32x2_r, 0);
 #endif
 
   return (int32_t)maximum;
@@ -326,17 +330,17 @@ static inline int32_t TransformAndFindMa
     outim1 += 4;
     vst1q_s32(outre2, outr_1);
     outre2 -= 4;
     vst1q_s32(outim2, outi_1);
     outim2 -= 4;
   }
 
   max_r = vmaxq_u32(max_r, max_i);
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   uint32_t maximum = vmaxvq_u32(max_r);
 #else
   uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
   max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
   uint32_t maximum = vget_lane_u32(max32x2_r, 0);
 #endif
 
   return (int32_t)maximum;
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_neon.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_neon.cc
@@ -9,17 +9,21 @@
  */
 
 /*
  * The core AEC algorithm, neon version of speed-critical functions.
  *
  * Based on aec_core_sse2.c.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 #include <math.h>
 #include <string.h>  // memset
 
 extern "C" {
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 }
 #include "modules/audio_processing/aec/aec_common.h"
 #include "modules/audio_processing/aec/aec_core_optimized_methods.h"
@@ -94,17 +98,18 @@ static float32x4_t vdivq_f32(float32x4_t
   //
   // Note: The precision did not improve after 2 iterations.
   for (i = 0; i < 2; i++) {
     x = vmulq_f32(vrecpsq_f32(b, x), x);
   }
   // a/b = a*(1/b)
   return vmulq_f32(a, x);
 }
-
+#endif
+#if !defined(WEBRTC_ARCH_ARM64) || (defined(_MSC_VER) && !defined(__clang__))
 static float32x4_t vsqrtq_f32(float32x4_t s) {
   int i;
   float32x4_t x = vrsqrteq_f32(s);
 
   // Code to handle sqrt(0).
   // If the input to sqrtf() is zero, a zero will be returned.
   // If the input to vrsqrteq_f32() is zero, positive infinity is returned.
   const uint32x4_t vec_p_inf = vdupq_n_u32(0x7F800000);
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
@@ -6,18 +6,22 @@
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "modules/audio_processing/aec3/adaptive_fir_filter.h"
 
 #if defined(WEBRTC_HAS_NEON)
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
 #endif
+#endif
 #include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
 #include <algorithm>
 #include <functional>
 
 #include "modules/audio_processing/aec3/fft_data.h"
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/matched_filter.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/matched_filter.cc
@@ -5,18 +5,22 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 #include "modules/audio_processing/aec3/matched_filter.h"
 
 #if defined(WEBRTC_HAS_NEON)
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
 #endif
+#endif
 #include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
 #include <algorithm>
 #include <numeric>
 
 #include "modules/audio_processing/include/audio_processing.h"
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/vector_math.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec3/vector_math.h
@@ -8,18 +8,22 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #ifndef MODULES_AUDIO_PROCESSING_AEC3_VECTOR_MATH_H_
 #define MODULES_AUDIO_PROCESSING_AEC3_VECTOR_MATH_H_
 
 #include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_HAS_NEON)
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
 #endif
+#endif
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
 #include <math.h>
 #include <algorithm>
 #include <array>
 #include <functional>
 
@@ -59,17 +63,17 @@ class VectorMath {
 #if defined(WEBRTC_HAS_NEON)
       case Aec3Optimization::kNeon: {
         const int x_size = static_cast<int>(x.size());
         const int vector_limit = x_size >> 2;
 
         int j = 0;
         for (; j < vector_limit * 4; j += 4) {
           float32x4_t g = vld1q_f32(&x[j]);
-#if !defined(WEBRTC_ARCH_ARM64)
+#if !defined(WEBRTC_ARCH_ARM64) || (defined(_MSC_VER) && !defined(__clang__))
           float32x4_t y = vrsqrteq_f32(g);
 
           // Code to handle sqrt(0).
           // If the input to sqrtf() is zero, a zero will be returned.
           // If the input to vrsqrteq_f32() is zero, positive infinity is
           // returned.
           const uint32x4_t vec_p_inf = vdupq_n_u32(0x7F800000);
           // check for divide by zero
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/aecm/aecm_core_neon.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aecm/aecm_core_neon.cc
@@ -5,26 +5,30 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "modules/audio_processing/aecm/aecm_core.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "common_audio/signal_processing/include/real_fft.h"
 #include "rtc_base/checks.h"
 
 // TODO(kma): Re-write the corresponding assembly file, the offset
 // generating script and makefile, to replace these C functions.
 
 static inline void AddLanes(uint32_t* ptr, uint32x4_t v) {
-#if defined(WEBRTC_ARCH_ARM64)
+#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
   *(ptr) = vaddvq_u32(v);
 #else
   uint32x2_t tmp_v;
   tmp_v = vadd_u32(vget_low_u32(v), vget_high_u32(v));
   tmp_v = vpadd_u32(tmp_v, tmp_v);
   *(ptr) = vget_lane_u32(tmp_v, 0);
 #endif
 }
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/ns/nsx_core_neon.c
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/ns/nsx_core_neon.c
@@ -5,17 +5,21 @@
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include "modules/audio_processing/ns/nsx_core.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "rtc_base/checks.h"
 
 // Constants to compensate for shifting signal log(2^shifts).
 const int16_t WebRtcNsx_kLogTable[9] = {
   0, 177, 355, 532, 710, 887, 1065, 1242, 1420
 };
 
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/utility/ooura_fft_neon.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/utility/ooura_fft_neon.cc
@@ -11,17 +11,21 @@
 /*
  * The rdft AEC algorithm, neon version of speed-critical functions.
  *
  * Based on the sse2 version.
  */
 
 #include "modules/audio_processing/utility/ooura_fft.h"
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "modules/audio_processing/utility/ooura_fft_tables_common.h"
 #include "modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h"
 
 namespace webrtc {
 
 #if defined(WEBRTC_HAS_NEON)
 void cft1st_128_neon(float* a) {
--- a/media/webrtc/trunk/webrtc/modules/video_processing/util/denoiser_filter_neon.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_processing/util/denoiser_filter_neon.cc
@@ -3,17 +3,21 @@
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <arm64_neon.h>
+#else
 #include <arm_neon.h>
+#endif
 
 #include "modules/video_processing/util/denoiser_filter_neon.h"
 
 namespace webrtc {
 
 const int kSumDiffThresholdHighNeon = 600;
 
 static int HorizontalAddS16x8(const int16x8_t v_16x8) {
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -16,16 +16,17 @@ skip-if = os == "android" # Android does
 [test_ext_background_window_properties.js]
 skip-if = os == "android"
 [test_ext_browserSettings.js]
 [test_ext_browserSettings_homepage.js]
 skip-if = appname == "thunderbird" || os == "android"
 [test_ext_cookieBehaviors.js]
 [test_ext_cookies_samesite.js]
 [test_ext_content_security_policy.js]
+skip-if = (os == "win" && debug) #Bug 1485567
 [test_ext_contentscript_api_injection.js]
 [test_ext_contentscript_async_loading.js]
 skip-if = os == 'android' && debug # The generated script takes too long to load on Android debug
 [test_ext_contentscript_context.js]
 [test_ext_contentscript_context_isolation.js]
 [test_ext_contentscript_create_iframe.js]
 [test_ext_contentscript_css.js]
 [test_ext_contentscript_exporthelpers.js]