Merge inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Wed, 14 Nov 2018 11:51:31 +0200
changeset 502594 073045259e75
parent 502569 d8a262837cd3 (current diff)
parent 502593 d3f4d556a89d (diff)
child 502595 7e059804fdf2
child 502607 29663ef51322
child 502669 ab76c815c205
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
073045259e75 / 65.0a1 / 20181114100226 / files
nightly linux64
073045259e75 / 65.0a1 / 20181114100226 / files
nightly mac
073045259e75 / 65.0a1 / 20181114100226 / files
nightly win32
073045259e75 / 65.0a1 / 20181114100226 / files
nightly win64
073045259e75 / 65.0a1 / 20181114100226 / 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
dom/notification/Notification.cpp
js/src/jsapi-tests/binast/parser/multipart/unit/let_in_fun.binjs
js/src/jsapi-tests/binast/parser/multipart/unit/let_in_fun.js
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -35,17 +35,17 @@ function appUpdater(options = {}) {
                                      "@mozilla.org/updates/update-checker;1",
                                      "nsIUpdateChecker");
   XPCOMUtils.defineLazyServiceGetter(this, "um",
                                      "@mozilla.org/updates/update-manager;1",
                                      "nsIUpdateManager");
 
   this.options = options;
   this.updateDeck = document.getElementById("updateDeck");
-  this.promiseAutoUpdateSetting = null;
+  this.promiseAutoUpdateSetting;
 
   // Hide the update deck when the update window is already open and it's not
   // already applied, to avoid syncing issues between them. Applied updates
   // don't have any information to sync between the windows as they both just
   // show the "Restart to continue"-type button.
   if (Services.wm.getMostRecentWindow("Update:Wizard") &&
       !this.isApplied) {
     this.updateDeck.hidden = true;
@@ -251,20 +251,20 @@ appUpdater.prototype =
         return;
       }
 
       if (!gAppUpdater.aus.canApplyUpdates) {
         gAppUpdater.selectPanel("manualUpdate");
         return;
       }
 
-      if (this.promiseAutoUpdateSetting == null) {
-        this.promiseAutoUpdateSetting = this.aus.getAutoUpdateIsEnabled();
+      if (!gAppUpdater.promiseAutoUpdateSetting) {
+        gAppUpdater.promiseAutoUpdateSetting = gAppUpdater.aus.getAutoUpdateIsEnabled();
       }
-      this.promiseAutoUpdateSetting.then(updateAuto => {
+      gAppUpdater.promiseAutoUpdateSetting.then(updateAuto => {
         if (updateAuto) { // automatically download and install
           gAppUpdater.startDownload();
         } else { // ask
           gAppUpdater.selectPanel("downloadAndInstall");
         }
       });
     },
 
--- a/devtools/client/inspector/flexbox/test/browser.ini
+++ b/devtools/client/inspector/flexbox/test/browser.ini
@@ -12,25 +12,33 @@ support-files =
   !/devtools/client/inspector/test/head.js
   !/devtools/client/inspector/test/shared-head.js
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
   !/devtools/client/shared/test/test-actor.js
   !/devtools/client/shared/test/test-actor-registry.js
 
+[browser_flexbox_accordion_state.js]
+[browser_flexbox_container_and_item.js]
+[browser_flexbox_container_element_rep.js]
+[browser_flexbox_empty_state.js]
 [browser_flexbox_highlighter_color_picker_on_ESC.js]
 [browser_flexbox_highlighter_color_picker_on_RETURN.js]
+[browser_flexbox_item_list_01.js]
+[browser_flexbox_item_list_02.js]
 [browser_flexbox_item_outline_exists.js]
 [browser_flexbox_item_outline_has_correct_layout.js]
 [browser_flexbox_item_outline_hidden_when_useless.js]
 [browser_flexbox_item_outline_renders_basisfinal_points_correctly.js]
 [browser_flexbox_item_outline_rotates_for_column.js]
 [browser_flexbox_pseudo_elements_are_listed.js]
 [browser_flexbox_sizing_flexibility_not_displayed_when_useless.js]
 [browser_flexbox_sizing_info_do_not_show_unspecified_min_dimension.js]
 [browser_flexbox_sizing_info_exists.js]
 [browser_flexbox_sizing_info_for_different_writing_modes.js]
 [browser_flexbox_sizing_info_for_pseudos.js]
 [browser_flexbox_sizing_info_for_text_nodes.js]
 [browser_flexbox_sizing_info_has_correct_sections.js]
 [browser_flexbox_sizing_wanted_to_grow_but_was_clamped.js]
 [browser_flexbox_text_nodes_are_listed.js]
+[browser_flexbox_toggle_flexbox_highlighter_01.js]
+[browser_flexbox_toggle_flexbox_highlighter_02.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_accordion_state.js
@@ -0,0 +1,76 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the flexbox's accordion state is persistent through hide/show in the layout
+// view.
+
+const TEST_URI = URL_ROOT + "doc_flexbox_specific_cases.html";
+
+const FLEXBOX_OPENED_PREF = "devtools.layout.flexbox.opened";
+
+add_task(async function() {
+  await addTab(TEST_URI);
+  const { inspector, flexboxInspector, toolbox } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+
+  await testAccordionStateAfterClickingHeader(doc);
+  await testAccordionStateAfterSwitchingSidebars(inspector, doc);
+  await testAccordionStateAfterReopeningLayoutView(toolbox);
+
+  Services.prefs.clearUserPref(FLEXBOX_OPENED_PREF);
+});
+
+function testAccordionStateAfterClickingHeader(doc) {
+  const header = doc.querySelector(".flexbox-pane ._header");
+  const content = doc.querySelector(".flexbox-pane ._content");
+
+  info("Checking initial state of the flexbox panel.");
+  is(content.style.display, "block", "The flexbox panel content is 'display: block'.");
+  ok(Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
+    `${FLEXBOX_OPENED_PREF} is pref on by default.`);
+
+  info("Clicking the flexbox header to hide the flexbox panel.");
+  header.click();
+
+  info("Checking the new state of the flexbox panel.");
+  is(content.style.display, "none", "The flexbox panel content is 'display: none'.");
+  ok(!Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
+    `${FLEXBOX_OPENED_PREF} is pref off.`);
+}
+
+function testAccordionStateAfterSwitchingSidebars(inspector, doc) {
+  info("Checking the flexbox accordion state is persistent after switching sidebars.");
+
+  const content = doc.querySelector(".flexbox-pane ._content");
+
+  info("Selecting the computed view.");
+  inspector.sidebar.select("computedview");
+
+  info("Selecting the layout view.");
+  inspector.sidebar.select("layoutview");
+
+  info("Checking the state of the flexbox panel.");
+  is(content.style.display, "none", "The flexbox panel content is 'display: none'.");
+  ok(!Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
+    `${FLEXBOX_OPENED_PREF} is pref off.`);
+}
+
+async function testAccordionStateAfterReopeningLayoutView(toolbox) {
+  info("Checking the flexbox accordion state is persistent after closing and re-opening "
+    + "the layout view.");
+
+  info("Closing the toolbox.");
+  await toolbox.destroy();
+
+  info("Re-opening the layout view.");
+  const { flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+  const content = doc.querySelector(".flexbox-pane ._content");
+
+  info("Checking the state of the flexbox panel.");
+  ok(!content, "The flexbox panel content is not rendered.");
+  ok(!Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
+    `${FLEXBOX_OPENED_PREF} is pref off.`);
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_container_and_item.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the flex container accordion and flex item accordion are both rendered when
+// the selected element is both a flex container and item.
+
+const TEST_URI = `
+  <style type='text/css'>
+    .container {
+      display: flex;
+    }
+  </style>
+  <div id="container" class="container">
+    <div id="item" class="container">
+      <div></div>
+    </div>
+  </div>
+`;
+
+add_task(async function() {
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+
+  const onAccordionsRendered = waitForDOM(doc, ".accordion > div", 4);
+  await selectNode("#item", inspector);
+  const [flexItemPane, flexContainerPane] = await onAccordionsRendered;
+
+  ok(flexItemPane, "The flex item accordion pane is rendered.");
+  ok(flexContainerPane, "The flex container accordion pane is rendered.");
+  is(flexItemPane.children[0].textContent, "Flex Item of div#container.container",
+    "Got the correct header for the flex item pane.");
+  is(flexContainerPane.children[0].textContent, "Flex Container",
+    "Got the correct header for the flex container pane.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_container_element_rep.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the flex container's element rep will display the box model highlighter on
+// hover.
+
+const TEST_URI = URL_ROOT + "doc_flexbox_specific_cases.html";
+
+add_task(async function() {
+  await addTab(TEST_URI);
+  const { inspector, flexboxInspector, toolbox } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+
+  const onFlexContainerRepRendered = waitForDOM(doc, ".flex-header-content .objectBox");
+  await selectNode("#container", inspector);
+  const [flexContainerRep] = await onFlexContainerRepRendered;
+
+  ok(flexContainerRep, "The flex container element rep is rendered.");
+
+  info("Listen to node-highlight event and mouse over the rep");
+  const onHighlight = toolbox.once("node-highlight");
+  EventUtils.synthesizeMouse(flexContainerRep, 10, 5, {type: "mouseover"},
+    doc.defaultView);
+  const nodeFront = await onHighlight;
+
+  ok(nodeFront, "nodeFront was returned from highlighting the node.");
+  is(nodeFront.tagName, "DIV", "The highlighted node has the correct tagName.");
+  is(nodeFront.attributes[0].name, "id",
+    "The highlighted node has the correct attributes.");
+  is(nodeFront.attributes[0].value, "container",
+    "The highlighted node has the correct id.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_empty_state.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that a message is displayed when no flex container is selected.
+
+const TEST_URI = `
+  <div></div>
+`;
+
+add_task(async function() {
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+  const { highlighters } = inspector;
+
+  info("Checking the initial state of the Flexbox Inspector.");
+  ok(doc.querySelector(".flexbox-pane .devtools-sidepanel-no-result",
+    "A message is displayede when no flex container is selected."));
+  ok(!highlighters.flexboxHighlighterShown,
+    "No flexbox highlighter exists in the highlighters overlay.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_item_list_01.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the flex item list is empty when there are no flex items for the selected flex
+// container.
+
+const TEST_URI = `
+  <div id="container" style="display:flex">
+  </div>
+`;
+
+add_task(async function() {
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+  const { highlighters } = inspector;
+
+  const onFlexHeaderRendered = waitForDOM(doc, ".flex-header");
+  await selectNode("#container", inspector);
+  const [flexHeader] = await onFlexHeaderRendered;
+  const flexHighlighterToggle = flexHeader.querySelector("#flexbox-checkbox-toggle");
+  const flexItemList = doc.querySelector(".flex-item-list");
+
+  info("Checking the state of the Flexbox Inspector.");
+  ok(flexHeader, "The flex container header is rendered.");
+  ok(flexHighlighterToggle, "The flexbox highlighter toggle is rendered.");
+  ok(!flexItemList, "The flex item list is not rendered.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+  ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_item_list_02.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the flex item list can be used to navigated to the selected flex item.
+
+const TEST_URI = URL_ROOT + "doc_flexbox_specific_cases.html";
+
+add_task(async function() {
+  await addTab(TEST_URI);
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+
+  const onFlexItemListRendered = waitForDOM(doc, ".flex-item-list");
+  await selectNode("#container", inspector);
+  const [flexItemList] = await onFlexItemListRendered;
+
+  info("Checking the initial state of the flex item list.");
+  ok(flexItemList, "The flex item list is rendered.");
+  is(flexItemList.children.length, 1,
+    "Got the correct number of flex items in the list.");
+
+  info("Clicking on the first flex item to navigate to the flex item.");
+  const onFlexItemOutlineRendered = waitForDOM(doc, ".flex-outline-container");
+  flexItemList.querySelector("button").click();
+  const [flexOutlineContainer] = await onFlexItemOutlineRendered;
+
+  info("Checking the selected flex item state.");
+  ok(flexOutlineContainer, "The flex outline is rendered.");
+  ok(!doc.querySelector(".flex-item-list"), "The flex item list is not shown.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_toggle_flexbox_highlighter_01.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test toggling ON/OFF the flexbox highlighter from the flexbox inspector panel.
+
+const TEST_URI = URL_ROOT + "doc_flexbox_specific_cases.html";
+
+add_task(async function() {
+  await addTab(TEST_URI);
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+  const { highlighters, store } = inspector;
+
+  const onFlexHighlighterToggleRendered = waitForDOM(doc, "#flexbox-checkbox-toggle");
+  await selectNode("#container", inspector);
+  const [flexHighlighterToggle] = await onFlexHighlighterToggleRendered;
+
+  info("Checking the initial state of the Flexbox Inspector.");
+  ok(flexHighlighterToggle, "The flexbox highlighter toggle is rendered.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+  ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
+
+  await toggleHighlighterON(flexHighlighterToggle, highlighters, store);
+
+  info("Checking the flexbox highlighter is created.");
+  ok(highlighters.flexboxHighlighterShown, "Flexbox highlighter is shown.");
+  ok(flexHighlighterToggle.checked, "The flexbox highlighter toggle is checked.");
+
+  await toggleHighlighterOFF(flexHighlighterToggle, highlighters, store);
+
+  info("Checking the flexbox highlighter is not shown.");
+  ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_toggle_flexbox_highlighter_02.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test toggling ON/OFF the flexbox highlighter on different flex containers from the
+// flexbox inspector panel.
+
+const TEST_URI = URL_ROOT + "doc_flexbox_specific_cases.html";
+
+add_task(async function() {
+  await addTab(TEST_URI);
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+  const { highlighters, store } = inspector;
+
+  const onFlexHighlighterToggleRendered = waitForDOM(doc, "#flexbox-checkbox-toggle");
+  await selectNode("#container", inspector);
+  const [flexHighlighterToggle] = await onFlexHighlighterToggleRendered;
+
+  info("Checking the #container state of the Flexbox Inspector.");
+  ok(flexHighlighterToggle, "The flexbox highlighter toggle is rendered.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+  ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
+
+  info("Toggling ON the flexbox highlighter for #container from the layout panel.");
+  await toggleHighlighterON(flexHighlighterToggle, highlighters, store);
+
+  info("Checking the flexbox highlighter is created for #container.");
+  const highlightedNodeFront = store.getState().flexbox.flexContainer.nodeFront;
+  is(highlighters.flexboxHighlighterShown, highlightedNodeFront,
+    "Flexbox highlighter is shown for #container.");
+  ok(flexHighlighterToggle.checked, "The flexbox highlighter toggle is checked.");
+
+  info("Switching the selected flex container to .container.column");
+  const onToggleChange = waitUntilState(store, state => !state.flexbox.highlighted);
+  await selectNode(".container.column", inspector);
+  await onToggleChange;
+
+  info("Checking the .container.column state of the Flexbox Inspector.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+  is(highlighters.flexboxHighlighterShown, highlightedNodeFront,
+    "Flexbox highlighter is still shown for #container.");
+
+  info("Toggling ON the flexbox highlighter for .container.column from the layout "
+    + "panel.");
+  await toggleHighlighterON(flexHighlighterToggle, highlighters, store);
+
+  info("Checking the flexbox highlighter is created for .container.column");
+  is(highlighters.flexboxHighlighterShown,
+    store.getState().flexbox.flexContainer.nodeFront,
+    "Flexbox highlighter is shown for .container.column.");
+  ok(flexHighlighterToggle.checked, "The flexbox highlighter toggle is checked.");
+
+  await toggleHighlighterOFF(flexHighlighterToggle, highlighters, store);
+
+  info("Checking the flexbox highlighter is not shown.");
+  ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
+  ok(!flexHighlighterToggle.checked, "The flexbox highlighter toggle is unchecked.");
+});
--- a/devtools/client/inspector/flexbox/test/head.js
+++ b/devtools/client/inspector/flexbox/test/head.js
@@ -25,8 +25,48 @@ Services.prefs.setBoolPref("devtools.lay
 
 // Clear all set prefs.
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.flexboxinspector.enabled");
   Services.prefs.clearUserPref("devtools.layout.flexbox.opened");
   Services.prefs.clearUserPref("devtools.layout.boxmodel.opened");
   Services.prefs.clearUserPref("devtools.layout.grid.opened");
 });
+
+/**
+ * Toggles ON the flexbox highlighter given the flexbox highlighter button from the
+ * layout panel.
+ *
+ * @param  {DOMNode} button
+ *         The flexbox highlighter toggle button in the flex container panel.
+ * @param  {HighlightersOverlay} highlighters
+ *         The HighlightersOverlay instance.
+ * @param  {Store} store
+ *         The Redux store instance.
+ */
+async function toggleHighlighterON(button, highlighters, store) {
+  info("Toggling ON the flexbox highlighter from the layout panel.");
+  const onHighlighterShown = highlighters.once("flexbox-highlighter-shown");
+  const onToggleChange = waitUntilState(store, state => state.flexbox.highlighted);
+  button.click();
+  await onHighlighterShown;
+  await onToggleChange;
+}
+
+/**
+ * Toggles OFF the flexbox highlighter given the flexbox highlighter button from the
+ * layout panel.
+ *
+ * @param  {DOMNode} button
+ *         The flexbox highlighter toggle button in the flex container panel.
+ * @param  {HighlightersOverlay} highlighters
+ *         The HighlightersOverlay instance.
+ * @param  {Store} store
+ *         The Redux store instance.
+ */
+async function toggleHighlighterOFF(button, highlighters, store) {
+  info("Toggling OFF the flexbox highlighter from the layout panel.");
+  const onHighlighterHidden = highlighters.once("flexbox-highlighter-hidden");
+  const onToggleChange = waitUntilState(store, state => !state.flexbox.highlighted);
+  button.click();
+  await onHighlighterHidden;
+  await onToggleChange;
+}
--- a/devtools/client/netmonitor/src/assets/styles/Toolbar.css
+++ b/devtools/client/netmonitor/src/assets/styles/Toolbar.css
@@ -66,19 +66,16 @@
   padding-right: 10px;
   background-position: right center;
 }
 
 /* Throttling Button */
 
 #network-throttling-menu {
   margin-inline-start: 10px;
-  padding-left: 2px;
-  padding-right: 10px;
-  background-position: right center;
 }
 
 .devtools-checkbox {
   position: relative;
   vertical-align: middle;
   bottom: 1px;
 }
 
--- a/devtools/client/themes/toolbars.css
+++ b/devtools/client/themes/toolbars.css
@@ -228,8 +228,20 @@ splitter.devtools-horizontal-splitter,
 .devtools-dropdown-button .title {
   display: inline-block;
   overflow: hidden;
   padding-top: 0.15em;
   text-align: center;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
+
+/*
+ * Style for the Network throttling menu button. This is shared between the Responsive
+ * Design Mode and Network Monitor.
+ */
+
+#network-throttling-menu {
+  padding-left: 2px;
+  padding-right: 10px;
+  background-position: right center;
+}
+
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -1229,47 +1229,16 @@ private:
   const nsString mTag;
   const nsString mIcon;
   const nsString mData;
   const nsString mBehavior;
 };
 
 NS_IMPL_ISUPPORTS(ServiceWorkerNotificationObserver, nsIObserver)
 
-// For ServiceWorkers.
-bool
-Notification::DispatchNotificationClickEvent()
-{
-  MOZ_ASSERT(mWorkerPrivate);
-  MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
-  mWorkerPrivate->AssertIsOnWorkerThread();
-
-  NotificationEventInit options;
-  options.mNotification = this;
-
-  ErrorResult result;
-  RefPtr<EventTarget> target = mWorkerPrivate->GlobalScope();
-  RefPtr<NotificationEvent> event =
-    NotificationEvent::Constructor(target,
-                                   NS_LITERAL_STRING("notificationclick"),
-                                   options,
-                                   result);
-  if (NS_WARN_IF(result.Failed())) {
-    return false;
-  }
-
-  event->SetTrusted(true);
-  WantsPopupControlCheck popupControlCheck(event);
-  target->DispatchEvent(*event);
-  // We always return false since in case of dispatching on the serviceworker,
-  // there is no well defined window to focus. The script may use the
-  // Client.focus() API if it wishes.
-  return false;
-}
-
 bool
 Notification::DispatchClickEvent()
 {
   AssertIsOnTargetThread();
   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   event->InitEvent(NS_LITERAL_STRING("click"), false, true);
   event->SetTrusted(true);
   WantsPopupControlCheck popupControlCheck(event);
--- a/dom/notification/Notification.h
+++ b/dom/notification/Notification.h
@@ -311,17 +311,16 @@ public:
                                               ErrorResult& aRv);
 
   static NotificationPermission GetPermissionInternal(nsIPrincipal* aPrincipal,
                                                       ErrorResult& rv);
 
   static NotificationPermission TestPermission(nsIPrincipal* aPrincipal);
 
   bool DispatchClickEvent();
-  bool DispatchNotificationClickEvent();
 
   static nsresult RemovePermission(nsIPrincipal* aPrincipal);
   static nsresult OpenSettings(nsIPrincipal* aPrincipal);
 
   nsresult DispatchToMainThread(already_AddRefed<nsIRunnable>&& aRunnable);
 protected:
   Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
                const nsAString& aTitle, const nsAString& aBody,
--- a/dom/payments/PaymentRequest.cpp
+++ b/dom/payments/PaymentRequest.cpp
@@ -466,22 +466,24 @@ PaymentRequest::IsValidDetailsInit(const
 }
 
 nsresult
 PaymentRequest::IsValidDetailsUpdate(const PaymentDetailsUpdate& aDetails,
                                      const bool aRequestShipping)
 {
   nsAutoString message;
   // Check the amount.value and amount.currency of detail.total
-  nsresult rv = IsValidCurrencyAmount(NS_LITERAL_STRING("details.total"),
-                                      aDetails.mTotal.mAmount,
-                                      true, // isTotalItem
-                                      message);
-  if (NS_FAILED(rv)) {
-    return rv;
+  if (aDetails.mTotal.WasPassed()) {
+    nsresult rv = IsValidCurrencyAmount(NS_LITERAL_STRING("details.total"),
+                                        aDetails.mTotal.Value().mAmount,
+                                        true, // isTotalItem
+                                        message);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
   }
   return IsValidDetailsBase(aDetails, aRequestShipping, message);
 }
 
 nsresult
 PaymentRequest::IsValidDetailsBase(const PaymentDetailsBase& aDetails,
                                    const bool aRequestShipping,
                                    nsAString& aErrorMsg)
@@ -526,22 +528,24 @@ PaymentRequest::IsValidDetailsBase(const
   // Check payment details modifiers
   if (aDetails.mModifiers.WasPassed()) {
     const Sequence<PaymentDetailsModifier>& modifiers = aDetails.mModifiers.Value();
     for (const PaymentDetailsModifier& modifier : modifiers) {
       rv = IsValidPaymentMethodIdentifier(modifier.mSupportedMethods, aErrorMsg);
       if (NS_FAILED(rv)) {
         return rv;
       }
-      rv = IsValidCurrencyAmount(NS_LITERAL_STRING("details.modifiers.total"),
-                                 modifier.mTotal.mAmount,
-                                 true, // isTotalItem
-                                 aErrorMsg);
-      if (NS_FAILED(rv)) {
-        return rv;
+      if (modifier.mTotal.WasPassed()) {
+        rv = IsValidCurrencyAmount(NS_LITERAL_STRING("details.modifiers.total"),
+                                   modifier.mTotal.Value().mAmount,
+                                   true, // isTotalItem
+                                   aErrorMsg);
+        if (NS_FAILED(rv)) {
+          return rv;
+        }
       }
       if (modifier.mAdditionalDisplayItems.WasPassed()) {
         const Sequence<PaymentItem>& displayItems = modifier.mAdditionalDisplayItems.Value();
         for (const PaymentItem& displayItem : displayItems) {
           rv = IsValidCurrencyAmount(displayItem.mLabel,
                                      displayItem.mAmount,
                                      false,  // isTotalItem
                                      aErrorMsg);
--- a/dom/payments/PaymentRequestManager.cpp
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -69,17 +69,19 @@ ConvertModifier(JSContext* aCx,
     JS::RootedObject object(aCx, aModifier.mData.Value());
     nsresult rv = SerializeFromJSObject(aCx, object, serializedData);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   IPCPaymentItem total;
-  ConvertItem(aModifier.mTotal, total);
+  if (aModifier.mTotal.WasPassed()) {
+    ConvertItem(aModifier.mTotal.Value(), total);
+  }
 
   nsTArray<IPCPaymentItem> additionalDisplayItems;
   if (aModifier.mAdditionalDisplayItems.WasPassed()) {
     for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
       IPCPaymentItem displayItem;
       ConvertItem(item, displayItem);
       additionalDisplayItems.AppendElement(displayItem);
     }
@@ -190,32 +192,38 @@ ConvertDetailsUpdate(JSContext* aCx,
   nsresult rv = ConvertDetailsBase(aCx, aDetails, displayItems, shippingOptions,
                                    modifiers, aRequestShipping);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Convert required |total|
   IPCPaymentItem total;
-  ConvertItem(aDetails.mTotal, total);
+  if (aDetails.mTotal.WasPassed()) {
+    ConvertItem(aDetails.mTotal.Value(), total);
+  }
 
   // Convert |error|
   nsAutoString error;
   if (aDetails.mError.WasPassed()) {
     error = aDetails.mError.Value();
   }
 
   nsAutoString shippingAddressErrors;
-  if (!aDetails.mShippingAddressErrors.ToJSON(shippingAddressErrors)) {
-    return NS_ERROR_FAILURE;
+  if (aDetails.mShippingAddressErrors.WasPassed()) {
+    if (!aDetails.mShippingAddressErrors.Value().ToJSON(shippingAddressErrors)) {
+      return NS_ERROR_FAILURE;
+    }
   }
 
   nsAutoString payerErrors;
-  if (!aDetails.mPayerErrors.ToJSON(payerErrors)) {
-    return NS_ERROR_FAILURE;
+  if (aDetails.mPayerErrors.WasPassed()) {
+    if (!aDetails.mPayerErrors.Value().ToJSON(payerErrors)) {
+      return NS_ERROR_FAILURE;
+    }
   }
 
   nsAutoString paymentMethodErrors;
   if (aDetails.mPaymentMethodErrors.WasPassed()) {
     JS::RootedObject object(aCx, aDetails.mPaymentMethodErrors.Value());
     nsresult rv = SerializeFromJSObject(aCx, object, paymentMethodErrors);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -599,20 +607,28 @@ PaymentRequestManager::RetryPayment(JSCo
   aRequest->GetInternalId(requestId);
 
   nsAutoString error;
   if (aErrors.mError.WasPassed()) {
     error = aErrors.mError.Value();
   }
 
   nsAutoString shippingAddressErrors;
-  aErrors.mShippingAddress.ToJSON(shippingAddressErrors);
+  if (aErrors.mShippingAddress.WasPassed()) {
+    if (!aErrors.mShippingAddress.Value().ToJSON(shippingAddressErrors)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
 
   nsAutoString payerErrors;
-  aErrors.mPayer.ToJSON(payerErrors);
+  if (aErrors.mPayer.WasPassed()) {
+    if (!aErrors.mPayer.Value().ToJSON(payerErrors)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
 
   nsAutoString paymentMethodErrors;
   if (aErrors.mPaymentMethod.WasPassed()) {
     JS::RootedObject object(aCx, aErrors.mPaymentMethod.Value());
     nsresult rv = SerializeFromJSObject(aCx, object, paymentMethodErrors);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
--- a/dom/payments/PaymentResponse.cpp
+++ b/dom/payments/PaymentResponse.cpp
@@ -383,71 +383,75 @@ PaymentResponse::ValidatePaymentValidati
   const PaymentValidationErrors& aErrors)
 {
   // Should not be empty errors
   // check PaymentValidationErrors.error
   if (aErrors.mError.WasPassed() && !aErrors.mError.Value().IsEmpty()) {
     return NS_OK;
   }
   // check PaymentValidationErrors.payer
-  PayerErrors payerErrors(aErrors.mPayer);
-  if (payerErrors.mName.WasPassed() && !payerErrors.mName.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (payerErrors.mEmail.WasPassed() && !payerErrors.mEmail.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (payerErrors.mPhone.WasPassed() && !payerErrors.mPhone.Value().IsEmpty()) {
-    return NS_OK;
+  if (aErrors.mPayer.WasPassed()) {
+    PayerErrors payerErrors(aErrors.mPayer.Value());
+    if (payerErrors.mName.WasPassed() && !payerErrors.mName.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (payerErrors.mEmail.WasPassed() && !payerErrors.mEmail.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (payerErrors.mPhone.WasPassed() && !payerErrors.mPhone.Value().IsEmpty()) {
+      return NS_OK;
+    }
   }
   // check PaymentValidationErrors.paymentMethod
   if (aErrors.mPaymentMethod.WasPassed()) {
     return NS_OK;
   }
   // check PaymentValidationErrors.shippingAddress
-  AddressErrors addErrors(aErrors.mShippingAddress);
-  if (addErrors.mAddressLine.WasPassed() &&
-      !addErrors.mAddressLine.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mCity.WasPassed() && !addErrors.mCity.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mCountry.WasPassed() && !addErrors.mCountry.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mDependentLocality.WasPassed() &&
-      !addErrors.mDependentLocality.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mOrganization.WasPassed() &&
-      !addErrors.mOrganization.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mPhone.WasPassed() && !addErrors.mPhone.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mPostalCode.WasPassed() &&
-      !addErrors.mPostalCode.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mRecipient.WasPassed() &&
-      !addErrors.mRecipient.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mRegion.WasPassed() && !addErrors.mRegion.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mRegionCode.WasPassed() &&
-      !addErrors.mRegionCode.Value().IsEmpty()) {
-    return NS_OK;
-  }
-  if (addErrors.mSortingCode.WasPassed() &&
-      !addErrors.mSortingCode.Value().IsEmpty()) {
-    return NS_OK;
+  if (aErrors.mShippingAddress.WasPassed()) {
+    AddressErrors addErrors(aErrors.mShippingAddress.Value());
+    if (addErrors.mAddressLine.WasPassed() &&
+        !addErrors.mAddressLine.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mCity.WasPassed() && !addErrors.mCity.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mCountry.WasPassed() && !addErrors.mCountry.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mDependentLocality.WasPassed() &&
+        !addErrors.mDependentLocality.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mOrganization.WasPassed() &&
+        !addErrors.mOrganization.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mPhone.WasPassed() && !addErrors.mPhone.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mPostalCode.WasPassed() &&
+        !addErrors.mPostalCode.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mRecipient.WasPassed() &&
+        !addErrors.mRecipient.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mRegion.WasPassed() && !addErrors.mRegion.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mRegionCode.WasPassed() &&
+        !addErrors.mRegionCode.Value().IsEmpty()) {
+      return NS_OK;
+    }
+    if (addErrors.mSortingCode.WasPassed() &&
+        !addErrors.mSortingCode.Value().IsEmpty()) {
+      return NS_OK;
+    }
   }
   return NS_ERROR_DOM_ABORT_ERR;
 }
 
 NS_IMETHODIMP
 PaymentResponse::Notify(nsITimer* timer)
 {
   mTimer = nullptr;
--- a/dom/script/ScriptLoadHandler.cpp
+++ b/dom/script/ScriptLoadHandler.cpp
@@ -288,56 +288,53 @@ ScriptLoadHandler::EnsureKnownDataType(n
   MOZ_ASSERT(mRequest->IsUnknownDataType());
   MOZ_ASSERT(mRequest->IsLoading());
 
   nsCOMPtr<nsIRequest> req;
   nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
   MOZ_ASSERT(req, "StreamLoader's request went away prematurely");
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (ScriptLoader::BinASTEncodingEnabled()) {
-    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(req);
-    if (httpChannel) {
-      nsAutoCString mimeType;
-      httpChannel->GetContentType(mimeType);
-      if (mimeType.LowerCaseEqualsASCII(APPLICATION_JAVASCRIPT_BINAST)) {
-        if (mRequest->ShouldAcceptBinASTEncoding()) {
-          mRequest->SetBinASTSource();
-          TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
-          return NS_OK;
-        } else {
-          return NS_ERROR_FAILURE;
-        }
-      }
-    }
-  }
-
   if (mRequest->IsLoadingSource()) {
     mRequest->SetTextSource();
     TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
     return NS_OK;
   }
 
   nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(req));
   if (cic) {
     nsAutoCString altDataType;
     cic->GetAlternativeDataType(altDataType);
     if (altDataType.Equals(nsContentUtils::JSBytecodeMimeType())) {
       mRequest->SetBytecode();
       TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_bytecode");
-    } else {
-      MOZ_ASSERT(altDataType.IsEmpty());
-      mRequest->SetTextSource();
-      TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
+      return NS_OK;
     }
-  } else {
-    mRequest->SetTextSource();
-    TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
+    MOZ_ASSERT(altDataType.IsEmpty());
   }
 
+  if (ScriptLoader::BinASTEncodingEnabled()) {
+    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(req);
+    if (httpChannel) {
+      nsAutoCString mimeType;
+      httpChannel->GetContentType(mimeType);
+      if (mimeType.LowerCaseEqualsASCII(APPLICATION_JAVASCRIPT_BINAST)) {
+        if (mRequest->ShouldAcceptBinASTEncoding()) {
+          mRequest->SetBinASTSource();
+          TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
+          return NS_OK;
+        }
+        return NS_ERROR_FAILURE;
+      }
+    }
+  }
+
+  mRequest->SetTextSource();
+  TRACE_FOR_TEST(mRequest->Element(), "scriptloader_load_source");
+
   MOZ_ASSERT(!mRequest->IsUnknownDataType());
   MOZ_ASSERT(mRequest->IsLoading());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
                                     nsISupports* aContext,
--- a/dom/webidl/PaymentMethodChangeEvent.webidl
+++ b/dom/webidl/PaymentMethodChangeEvent.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  *
  * The origin of this WebIDL file is
- *   https://www.w3.org/TR/payment-request/#paymentmethodchangeevent-interface
+ *   https://w3c.github.io/payment-request/#paymentmethodchangeevent-interface
  *
  * Copyright © 2018 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict),
  SecureContext,
  Exposed=Window,
--- a/dom/webidl/PaymentRequest.webidl
+++ b/dom/webidl/PaymentRequest.webidl
@@ -1,15 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  *
  * The origin of this WebIDL file is
- *   https://www.w3.org/TR/payment-request/#paymentrequest-interface
+ *   https://w3c.github.io/payment-request/#paymentrequest-interface
+ *   https://w3c.github.io/payment-request/#idl-index
  *
  * Copyright © 2018 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 dictionary PaymentMethodData {
   required DOMString           supportedMethods;
            object              data;
@@ -30,18 +31,17 @@ dictionary PaymentShippingOption {
   required DOMString             id;
   required DOMString             label;
   required PaymentCurrencyAmount amount;
            boolean               selected = false;
 };
 
 dictionary PaymentDetailsModifier {
   required DOMString             supportedMethods;
-  // FIXME: bug 1493860: should this "= null" be here?
-           PaymentItem           total = null;
+           PaymentItem           total;
            sequence<PaymentItem> additionalDisplayItems;
            object                data;
 };
 
 dictionary PaymentDetailsBase {
   sequence<PaymentItem>            displayItems;
   sequence<PaymentShippingOption>  shippingOptions;
   sequence<PaymentDetailsModifier> modifiers;
@@ -62,39 +62,34 @@ dictionary AddressErrors {
   DOMString postalCode;
   DOMString recipient;
   DOMString region;
   DOMString regionCode;
   DOMString sortingCode;
 };
 
 dictionary PaymentValidationErrors {
-  // FIXME: bug 1493860: should this "= null" be here?
-  PayerErrors payer = null;
-  // FIXME: bug 1493860: should this "= null" be here?
-  AddressErrors shippingAddress = null;
+  PayerErrors payer;
+  AddressErrors shippingAddress;
   DOMString error;
   object paymentMethod;
 };
 
 dictionary PayerErrors {
   DOMString email;
   DOMString name;
   DOMString phone;
 };
 
 dictionary PaymentDetailsUpdate : PaymentDetailsBase {
   DOMString     error;
-  // FIXME: bug 1493860: should this "= null" be here?
-  AddressErrors shippingAddressErrors = null;
-  // FIXME: bug 1493860: should this "= null" be here?
-  PayerErrors payerErrors = null;
+  AddressErrors shippingAddressErrors;
+  PayerErrors payerErrors;
   object paymentMethodErrors;
-  // FIXME: bug 1493860: should this "= null" be here?
-  PaymentItem   total = null;
+  PaymentItem   total;
 };
 
 enum PaymentShippingType {
   "shipping",
   "delivery",
   "pickup"
 };
 
--- a/dom/webidl/PaymentRequestUpdateEvent.webidl
+++ b/dom/webidl/PaymentRequestUpdateEvent.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  *
  * The origin of this WebIDL file is
- *   https://www.w3.org/TR/payment-request/#paymentrequestupdateevent-interface
+ *   https://w3c.github.io/payment-request/#paymentrequestupdateevent-interface
  *
  * Copyright © 2018 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Constructor(DOMString type,
              optional PaymentRequestUpdateEventInit eventInitDict),
  SecureContext,
--- a/dom/webidl/PaymentResponse.webidl
+++ b/dom/webidl/PaymentResponse.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  *
  * The origin of this WebIDL file is
- *   https://www.w3.org/TR/payment-request/#paymentresponse-interface
+ *   https:/w3c.github.io/payment-request/#paymentresponse-interface
  *
  * Copyright © 2018 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 enum PaymentComplete {
   "success",
   "fail",
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-52926
+52944
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -16212,16 +16212,17 @@ baseness/M
 baser
 bash/GMDS
 bashful/PY
 bashfulness/M
 bashing/M
 basic/MS
 basically
 basil/M
+basilar
 basilica/MS
 basilisk/MS
 basin/MS
 basinful/MS
 basis/M
 bask/SGD
 basket/SM
 basketball/MS
@@ -22031,16 +22032,21 @@ cynic/SM
 cynical/Y
 cynicism/M
 cynosure/MS
 cypher/M
 cypress/MS
 cyst/MS
 cysteine/SM
 cystic
+cysticerci
+cysticercoid/S
+cysticercoses
+cysticercosis
+cysticercus
 cystitis
 cytokine/SM
 cytologist/SM
 cytology/M
 cytoplasm/M
 cytoplasmic
 cytosine/M
 czar/MS
@@ -25357,16 +25363,19 @@ everyday
 everyone/M
 everyplace
 everything/M
 everywhere
 evict/SDG
 eviction/MS
 evidence/MGDS
 evident/Y
+evidential/Y
+evidentiality
+evidentiary
 evil/MRYTSP
 evildoer/SM
 evildoing/M
 eviller
 evillest
 evilness/M
 evince/DSG
 eviscerate/DSGN
@@ -26369,17 +26378,17 @@ finality/M
 finalization/M
 finalize/DSG
 finance's
 finance/ADSG
 financial/YS
 financier/MS
 financing/M
 finch/MS
-find/JMRZGS
+find/JMRZGSB
 finder/M
 finding/M
 findings/M
 fine's/F
 fine/CAFTGDS
 finely
 fineness/M
 finery/AM
@@ -29376,16 +29385,17 @@ headrest/MS
 headroom/M
 headscarf
 headscarves
 headset/SM
 headship/SM
 headshrinker/SM
 headsman/M
 headsmen
+headspace
 headstall/SM
 headstand/SM
 headstone/SM
 headstrong
 headteacher/S
 headwaiter/SM
 headwaters/M
 headway/M
@@ -32590,16 +32600,17 @@ kitty/SM
 kiwi/MS
 kiwifruit/MS
 kl
 klaxon/S
 kleptocracy
 kleptomania/M
 kleptomaniac/SM
 kludge/GDS
+kludgy
 kluge/DS
 klutz/MS
 klutziness/M
 klutzy/TRP
 km
 kn
 knack/SZMR
 knacker/GD
@@ -36464,16 +36475,18 @@ network/SGMD
 networking/M
 neural/Y
 neuralgia/M
 neuralgic
 neurasthenia/M
 neurasthenic/MS
 neuritic/MS
 neuritis/M
+neurocysticercoses
+neurocysticercosis
 neurological/Y
 neurologist/SM
 neurology/M
 neuron/MS
 neuronal
 neurophysiology's
 neuroscience/MS
 neuroscientist/MS
@@ -40327,17 +40340,17 @@ pose/CAKEGDS
 poser/EKSM
 poseur/SM
 posh/TR
 posit/DSGV
 position/CKEMS
 positional/KE
 positioned/K
 positioning/AK
-positive/MYPS
+positive/MYPSE
 positiveness/M
 positivism
 positivist/S
 positivity/SM
 positron/MS
 poss
 posse/MS
 possess/AEVGSD
@@ -42654,16 +42667,17 @@ repulsiveness/M
 repurchase/GDS
 reputability/M
 reputably/E
 reputation/MS
 reputational
 repute/DSMGB
 reputed/Y
 request/GDR
+requestor
 requiem/SM
 require/LDG
 requirement/MS
 requisite/XMNS
 requisition/GMD
 requital/M
 requite/DRSZG
 requited/U
@@ -47697,16 +47711,17 @@ superpose/GDS
 superposition/M
 superpower/SM
 supersaturate/GNDS
 supersaturation/M
 superscribe/GDS
 superscript/MS
 superscription/M
 supersede/GDS
+superset
 supersize/GDS
 supersonic
 superstar/MS
 superstardom
 superstate/S
 superstition/MS
 superstitious/Y
 superstore/MS
@@ -48746,17 +48761,17 @@ thee/S
 theft/SM
 their/S
 theism/M
 theist/SM
 theistic
 them
 thematic
 thematically
-theme/DSM
+theme/DSMG
 themselves
 then/M
 thence
 thenceforth
 thenceforward
 theocracy/SM
 theocratic
 theodolite/S
@@ -50345,16 +50360,17 @@ uncongenial
 unconscionable
 unconscionably
 unconscious/M
 unconstitutional/Y
 uncontrollably
 uncontroversial
 uncool
 uncooperative
+uncopyrightable
 uncouth/Y
 uncrushable
 unction/SM
 unctuous/YP
 unctuousness/M
 uncut
 undaunted/Y
 undecided/SM
@@ -50502,16 +50518,17 @@ undulate/DSXGN
 undulation/M
 undying
 unearthliness/M
 unease/M
 uneasy/T
 uneatable
 uneconomic
 unemployed/M
+unencrypted
 unending
 unenterprising
 unequal/DY
 unerring/Y
 unessential
 uneven/Y
 unexceptionably
 unexcited
@@ -51171,16 +51188,17 @@ versioning
 verso/SM
 versus
 vert/A
 vertebra/M
 vertebrae
 vertebral
 vertebrata
 vertebrate/IMS
+vertebrobasilar
 vertex/MS
 vertical/MYS
 vertices
 vertiginous
 vertigo/M
 verve/M
 very/RT
 vesicle/SM
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -15,16 +15,23 @@
 #include "mozilla/layers/WebRenderTextureHost.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 
 namespace mozilla {
 namespace layers {
 
+AsyncImagePipelineManager::ForwardingExternalImage::~ForwardingExternalImage()
+{
+  DebugOnly<bool> released =
+    SharedSurfacesParent::Release(mImageId);
+    MOZ_ASSERT(released);
+}
+
 AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
  : mInitialised(false)
  , mIsChanged(false)
  , mUseExternalImage(false)
  , mFilter(wr::ImageRendering::Auto)
  , mMixBlendMode(wr::MixBlendMode::Normal)
 {}
 
@@ -47,16 +54,17 @@ AsyncImagePipelineManager::~AsyncImagePi
   MOZ_COUNT_DTOR(AsyncImagePipelineManager);
 }
 
 void
 AsyncImagePipelineManager::Destroy()
 {
   MOZ_ASSERT(!mDestroyed);
   mApi = nullptr;
+  mPipelineTexturesHolders.Clear();
   mDestroyed = true;
 }
 
 void
 AsyncImagePipelineManager::SetWillGenerateFrame()
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
 
@@ -535,17 +543,18 @@ AsyncImagePipelineManager::HoldExternalI
 
   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
   MOZ_ASSERT(holder);
   if (!holder) {
     SharedSurfacesParent::Release(aImageId);
     return;
   }
 
-  holder->mExternalImages.push(ForwardingExternalImage(aEpoch, aImageId));
+  auto image = MakeUnique<ForwardingExternalImage>(aEpoch, aImageId);
+  holder->mExternalImages.push(std::move(image));
 }
 
 void
 AsyncImagePipelineManager::NotifyPipelinesUpdated(const wr::WrPipelineInfo& aInfo, bool aRender)
 {
   // This is called on the render thread, so we just stash the data into
   // UpdatesQueue and process it later on the compositor thread.
   MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
@@ -653,22 +662,19 @@ AsyncImagePipelineManager::ProcessPipeli
     }
     while (!holder->mTextureHostWrappers.empty()) {
       if (aEpoch <= holder->mTextureHostWrappers.front().mEpoch) {
         break;
       }
       holder->mTextureHostWrappers.pop();
     }
     while (!holder->mExternalImages.empty()) {
-      if (aEpoch <= holder->mExternalImages.front().mEpoch) {
+      if (aEpoch <= holder->mExternalImages.front()->mEpoch) {
         break;
       }
-      DebugOnly<bool> released =
-        SharedSurfacesParent::Release(holder->mExternalImages.front().mImageId);
-      MOZ_ASSERT(released);
       holder->mExternalImages.pop();
     }
   }
 }
 
 void
 AsyncImagePipelineManager::ProcessPipelineRemoved(const wr::PipelineId& aPipelineId, const uint64_t aUpdatesCount)
 {
@@ -678,24 +684,16 @@ AsyncImagePipelineManager::ProcessPipeli
   if (auto entry = mPipelineTexturesHolders.Lookup(wr::AsUint64(aPipelineId))) {
     PipelineTexturesHolder* holder = entry.Data();
     if (holder->mDestroyedEpoch.isSome()) {
       while (!holder->mTextureHosts.empty()) {
         // Need to extend holding TextureHost if it is direct bounded texture.
         HoldUntilNotUsedByGPU(holder->mTextureHosts.front().mTexture, aUpdatesCount);
         holder->mTextureHosts.pop();
       }
-      // Explicitly release all of the shared surfaces.
-      while (!holder->mExternalImages.empty()) {
-        DebugOnly<bool> released =
-          SharedSurfacesParent::Release(holder->mExternalImages.front().mImageId);
-        MOZ_ASSERT(released);
-        holder->mExternalImages.pop();
-      }
-
       // Remove Pipeline
       entry.Remove();
     }
     // If mDestroyedEpoch contains nothing it means we reused the same pipeline id (probably because
     // we moved the tab to another window). In this case we need to keep the holder.
   }
 }
 
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -147,25 +147,26 @@ private:
     RefPtr<WebRenderTextureHostWrapper> mWrTextureWrapper;
   };
 
   struct ForwardingExternalImage {
     ForwardingExternalImage(const wr::Epoch& aEpoch, const wr::ExternalImageId& aImageId)
       : mEpoch(aEpoch)
       , mImageId(aImageId)
     {}
+    ~ForwardingExternalImage();
     wr::Epoch mEpoch;
     wr::ExternalImageId mImageId;
   };
 
   struct PipelineTexturesHolder {
     // Holds forwarding WebRenderTextureHosts.
     std::queue<ForwardingTextureHost> mTextureHosts;
     std::queue<ForwardingTextureHostWrapper> mTextureHostWrappers;
-    std::queue<ForwardingExternalImage> mExternalImages;
+    std::queue<UniquePtr<ForwardingExternalImage>> mExternalImages;
     Maybe<wr::Epoch> mDestroyedEpoch;
   };
 
   struct AsyncImagePipeline {
     AsyncImagePipeline();
     void Update(const LayoutDeviceRect& aScBounds,
                 const gfx::Matrix4x4& aScTransform,
                 const gfx::MaybeIntSize& aScaleToSize,
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -2618,20 +2618,26 @@ BinASTParser<Tok>::parseInterfaceForInOf
 
     BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
 
     BINJS_MOZ_TRY_DECL(binding, parseBinding());
 
     // Restored by `kindGuard`.
     variableDeclarationKind_ = kind_;
     MOZ_TRY(checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
-    auto pnk =
-        kind_ == VariableDeclarationKind::Let
-            ? ParseNodeKind::Let
-            : ParseNodeKind::Var;
+    ParseNodeKind pnk;
+    switch (kind_) {
+      case VariableDeclarationKind::Var:
+        pnk = ParseNodeKind::Var;
+        break;
+      case VariableDeclarationKind::Let:
+        return raiseError("Let is not supported in this preview release");
+      case VariableDeclarationKind::Const:
+        return raiseError("Const is not supported in this preview release");
+    }
     BINJS_TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
     factory_.addList(result, binding);
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
@@ -3944,21 +3950,19 @@ BinASTParser<Tok>::parseInterfaceVariabl
     }
 
     ParseNodeKind pnk;
     switch (kind_) {
       case VariableDeclarationKind::Var:
         pnk = ParseNodeKind::Var;
         break;
       case VariableDeclarationKind::Let:
-        pnk = ParseNodeKind::Let;
-        break;
+        return raiseError("Let is not supported in this preview release");
       case VariableDeclarationKind::Const:
-        pnk = ParseNodeKind::Const;
-        break;
+        return raiseError("Const is not supported in this preview release");
     }
     declarators->setKind(pnk);
     auto result = declarators;
     return result;
 }
 
 
 /*
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -839,20 +839,26 @@ ExpressionStatement:
 
 ForInOfBinding:
     init:
         AutoVariableDeclarationKind kindGuard(this);
     build: |
         // Restored by `kindGuard`.
         variableDeclarationKind_ = kind_;
         MOZ_TRY(checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
-        auto pnk =
-            kind_ == VariableDeclarationKind::Let
-                ? ParseNodeKind::Let
-                : ParseNodeKind::Var;
+        ParseNodeKind pnk;
+        switch (kind_) {
+          case VariableDeclarationKind::Var:
+            pnk = ParseNodeKind::Var;
+            break;
+          case VariableDeclarationKind::Let:
+            return raiseError("Let is not supported in this preview release");
+          case VariableDeclarationKind::Const:
+            return raiseError("Const is not supported in this preview release");
+        }
         BINJS_TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
         factory_.addList(result, binding);
 
 
 
 ForInStatement:
     init: |
         ParseContext::Statement stmt(parseContext_, StatementKind::ForInLoop);
@@ -1328,21 +1334,19 @@ VariableDeclaration:
         }
 
         ParseNodeKind pnk;
         switch (kind_) {
           case VariableDeclarationKind::Var:
             pnk = ParseNodeKind::Var;
             break;
           case VariableDeclarationKind::Let:
-            pnk = ParseNodeKind::Let;
-            break;
+            return raiseError("Let is not supported in this preview release");
           case VariableDeclarationKind::Const:
-            pnk = ParseNodeKind::Const;
-            break;
+            return raiseError("Const is not supported in this preview release");
         }
         declarators->setKind(pnk);
         auto result = declarators;
 
 VariableDeclarator:
     build: |
         ParseNode* result;
         if (binding->isKind(ParseNodeKind::Name)) {
--- a/js/src/frontend/BinTokenReaderBase.cpp
+++ b/js/src/frontend/BinTokenReaderBase.cpp
@@ -25,25 +25,18 @@ BinTokenReaderBase::updateLatestKnownGoo
     const size_t update = current_ - start_;
     MOZ_ASSERT(update >= latestKnownGoodPos_);
     latestKnownGoodPos_ = update;
 }
 
 ErrorResult<JS::Error&>
 BinTokenReaderBase::raiseError(const char* description)
 {
-    MOZ_ASSERT(!cx_->isExceptionPending());
-    if (MOZ_LIKELY(errorReporter_)) {
-        errorReporter_->reportErrorNoOffset(JSMSG_BINAST, description);
-    } else {
-        // Only true in testing code.
-        TokenPos pos = this->pos();
-        JS_ReportErrorASCII(cx_, "BinAST parsing error: %s at offsets %u => %u",
-                            description, pos.begin, pos.end);
-    }
+    MOZ_ASSERT(!hasRaisedError());
+    errorReporter_->reportErrorNoOffset(JSMSG_BINAST, description);
     return cx_->alreadyReportedError();
 }
 
 ErrorResult<JS::Error&>
 BinTokenReaderBase::raiseOOM()
 {
     ReportOutOfMemory(cx_);
     return cx_->alreadyReportedError();
@@ -63,23 +56,27 @@ ErrorResult<JS::Error&>
 BinTokenReaderBase::raiseInvalidField(const char* kind, const BinField field)
 {
     Sprinter out(cx_);
     BINJS_TRY(out.init());
     BINJS_TRY(out.printf("In %s, invalid field '%s'", kind, describeBinField(field)));
     return raiseError(out.string());
 }
 
-#ifdef DEBUG
 bool
 BinTokenReaderBase::hasRaisedError() const
 {
+    if (cx_->helperThread()) {
+        // When performing off-main-thread parsing, we don't set a pending
+        // exception but instead add a pending compile error.
+        return cx_->isCompileErrorPending();
+    }
+
     return cx_->isExceptionPending();
 }
-#endif
 
 size_t
 BinTokenReaderBase::offset() const
 {
     return current_ - start_;
 }
 
 TokenPos
@@ -104,17 +101,17 @@ BinTokenReaderBase::seek(size_t offset)
     MOZ_ASSERT(start_ + offset >= start_ &&
                start_ + offset < stop_);
     current_ = start_ + offset;
 }
 
 JS::Result<Ok>
 BinTokenReaderBase::readBuf(uint8_t* bytes, uint32_t len)
 {
-    MOZ_ASSERT(!cx_->isExceptionPending());
+    MOZ_ASSERT(!hasRaisedError());
     MOZ_ASSERT(len > 0);
 
     if (stop_ < current_ + len) {
         return raiseError("Buffer exceeds length");
     }
 
     for (uint32_t i = 0; i < len; ++i) {
         *bytes++ = *current_++;
--- a/js/src/frontend/BinTokenReaderBase.h
+++ b/js/src/frontend/BinTokenReaderBase.h
@@ -80,17 +80,19 @@ class MOZ_STACK_CLASS BinTokenReaderBase
     BinTokenReaderBase(JSContext* cx, ErrorReporter* er, const uint8_t* start, const size_t length)
         : cx_(cx)
         , errorReporter_(er)
         , poisoned_(false)
         , start_(start)
         , current_(start)
         , stop_(start + length)
         , latestKnownGoodPos_(0)
-    { }
+    {
+        MOZ_ASSERT(errorReporter_);
+    }
 
     /**
      * Read a single byte.
      */
     MOZ_MUST_USE JS::Result<uint8_t> readByte();
 
     /**
      * Read several bytes.
@@ -146,19 +148,17 @@ class MOZ_STACK_CLASS BinTokenReaderBase
         // Looks like we have a match. Now perform side-effects
         current_ += N + (expectNul ? 0 : -1);
         updateLatestKnownGood();
         return true;
     }
 
     void updateLatestKnownGood();
 
-#ifdef DEBUG
     bool hasRaisedError() const;
-#endif
 
     JSContext* cx_;
 
     ErrorReporter* errorReporter_;
 
     // `true` if we have encountered an error. Errors are non recoverable.
     // Attempting to read from a poisoned tokenizer will cause assertion errors.
     bool poisoned_;
--- a/js/src/frontend/BinTokenReaderMultipart.cpp
+++ b/js/src/frontend/BinTokenReaderMultipart.cpp
@@ -427,17 +427,17 @@ BinTokenReaderMultipart::AutoBase::AutoB
     , reader_(reader)
 { }
 
 BinTokenReaderMultipart::AutoBase::~AutoBase()
 {
     // By now, the `AutoBase` must have been deinitialized by calling `done()`.
     // The only case in which we can accept not calling `done()` is if we have
     // bailed out because of an error.
-    MOZ_ASSERT_IF(initialized_, reader_.cx_->isExceptionPending());
+    MOZ_ASSERT_IF(initialized_, reader_.hasRaisedError());
 }
 
 JS::Result<Ok>
 BinTokenReaderMultipart::AutoBase::checkPosition(const uint8_t* expectedEnd)
 {
     if (reader_.current_ != expectedEnd) {
         return reader_.raiseError("Caller did not consume the expected set of bytes");
     }
@@ -457,17 +457,17 @@ BinTokenReaderMultipart::AutoList::init(
     AutoBase::init();
 }
 
 JS::Result<Ok>
 BinTokenReaderMultipart::AutoList::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     return Ok();
 }
 
 
@@ -508,34 +508,34 @@ BinTokenReaderMultipart::AutoTaggedTuple
     : AutoBase(reader)
 { }
 
 JS::Result<Ok>
 BinTokenReaderMultipart::AutoTaggedTuple::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     return Ok();
 }
 
 BinTokenReaderMultipart::AutoTuple::AutoTuple(BinTokenReaderMultipart& reader)
     : AutoBase(reader)
 { }
 
 JS::Result<Ok>
 BinTokenReaderMultipart::AutoTuple::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     // Check suffix.
     return Ok();
 }
 
--- a/js/src/frontend/BinTokenReaderTester.cpp
+++ b/js/src/frontend/BinTokenReaderTester.cpp
@@ -394,17 +394,17 @@ BinTokenReaderTester::AutoBase::AutoBase
     , reader_(reader)
 { }
 
 BinTokenReaderTester::AutoBase::~AutoBase()
 {
     // By now, the `AutoBase` must have been deinitialized by calling `done()`.
     // The only case in which we can accept not calling `done()` is if we have
     // bailed out because of an error.
-    MOZ_ASSERT_IF(initialized_, reader_.cx_->isExceptionPending());
+    MOZ_ASSERT_IF(initialized_, reader_.hasRaisedError());
 }
 
 JS::Result<Ok>
 BinTokenReaderTester::AutoBase::checkPosition(const uint8_t* expectedEnd)
 {
     if (reader_.current_ != expectedEnd) {
         return reader_.raiseError("Caller did not consume the expected set of bytes");
     }
@@ -422,17 +422,17 @@ BinTokenReaderTester::AutoList::init()
     AutoBase::init();
 }
 
 JS::Result<Ok>
 BinTokenReaderTester::AutoList::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     // Check suffix.
     MOZ_TRY(reader_.readConst("</list>"));
 
     return Ok();
@@ -442,17 +442,17 @@ BinTokenReaderTester::AutoTaggedTuple::A
     : AutoBase(reader)
 { }
 
 JS::Result<Ok>
 BinTokenReaderTester::AutoTaggedTuple::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     // Check suffix.
     MOZ_TRY(reader_.readConst("</tuple>"));
 
     return Ok();
@@ -462,17 +462,17 @@ BinTokenReaderTester::AutoTuple::AutoTup
     : AutoBase(reader)
 { }
 
 JS::Result<Ok>
 BinTokenReaderTester::AutoTuple::done()
 {
     MOZ_ASSERT(initialized_);
     initialized_ = false;
-    if (reader_.cx_->isExceptionPending()) {
+    if (reader_.hasRaisedError()) {
         // Already errored, no need to check further.
         return reader_.cx_->alreadyReportedError();
     }
 
     // Check suffix.
     MOZ_TRY(reader_.readConst("</tuple>"));
 
     return Ok();
--- a/js/src/gc/GenerateStatsPhases.py
+++ b/js/src/gc/GenerateStatsPhases.py
@@ -302,31 +302,31 @@ def generateHeader(out):
     #
     out.write("static const size_t MAX_PHASE_NESTING = %d;\n" % MaxPhaseNesting)
 
 
 def generateCpp(out):
     #
     # Generate the PhaseKindInfo table.
     #
-    out.write("static const PhaseKindTable phaseKinds = {\n")
+    out.write("static constexpr PhaseKindTable phaseKinds = {\n")
     for phaseKind in AllPhaseKinds:
         phase = PhasesForPhaseKind[phaseKind][0]
         out.write("    /* PhaseKind::%s */ PhaseKindInfo { Phase::%s, %d },\n" %
                   (phaseKind.name, phase.name, phaseKind.bucket))
     out.write("};\n")
     out.write("\n")
 
     #
     # Generate the PhaseInfo tree.
     #
     def name(phase):
         return "Phase::" + phase.name if phase else "Phase::NONE"
 
-    out.write("static const PhaseTable phases = {\n")
+    out.write("static constexpr PhaseTable phases = {\n")
     for phase in AllPhases:
         firstChild = phase.children[0] if phase.children else None
         phaseKind = phase.phaseKind
         out.write("    /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\", \"%s\" },\n" %  # NOQA: E501
                   (name(phase),
                    name(phase.parent),
                    name(firstChild),
                    name(phase.nextSibling),
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -174,60 +174,82 @@ CodeGeneratorARM64::bailoutFrom(Label* l
     addOutOfLineCode(ool, new(alloc()) BytecodeSite(tree, tree->script()->code()));
 
     masm.retarget(label, ool->entry());
 }
 
 void
 CodeGeneratorARM64::bailout(LSnapshot* snapshot)
 {
-    MOZ_CRASH("bailout");
+    Label label;
+    masm.b(&label);
+    bailoutFrom(&label, snapshot);
 }
 
 void
 CodeGeneratorARM64::visitOutOfLineBailout(OutOfLineBailout* ool)
 {
     masm.push(Imm32(ool->snapshot()->snapshotOffset()));
     masm.B(&deoptLabel_);
 }
 
 void
 CodeGenerator::visitMinMaxD(LMinMaxD* ins)
 {
-    MOZ_CRASH("visitMinMaxD");
+    ARMFPRegister lhs(ToFloatRegister(ins->first()), 64);
+    ARMFPRegister rhs(ToFloatRegister(ins->second()), 64);
+    ARMFPRegister output(ToFloatRegister(ins->output()), 64);
+    if (ins->mir()->isMax()) {
+        masm.Fmax(output, lhs, rhs);
+    } else {
+        masm.Fmin(output, lhs, rhs);
+    }
 }
 
 void
 CodeGenerator::visitMinMaxF(LMinMaxF* ins)
 {
-    MOZ_CRASH("visitMinMaxF");
+    ARMFPRegister lhs(ToFloatRegister(ins->first()), 32);
+    ARMFPRegister rhs(ToFloatRegister(ins->second()), 32);
+    ARMFPRegister output(ToFloatRegister(ins->output()), 32);
+    if (ins->mir()->isMax()) {
+        masm.Fmax(output, lhs, rhs);
+    } else {
+        masm.Fmin(output, lhs, rhs);
+    }
 }
 
 void
 CodeGenerator::visitAbsD(LAbsD* ins)
 {
-    MOZ_CRASH("visitAbsD");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 64);
+    masm.Fabs(input, input);
 }
 
 void
 CodeGenerator::visitAbsF(LAbsF* ins)
 {
-    MOZ_CRASH("visitAbsF");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 32);
+    masm.Fabs(input, input);
 }
 
 void
 CodeGenerator::visitSqrtD(LSqrtD* ins)
 {
-    MOZ_CRASH("visitSqrtD");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 64);
+    ARMFPRegister output(ToFloatRegister(ins->output()), 64);
+    masm.Fsqrt(output, input);
 }
 
 void
 CodeGenerator::visitSqrtF(LSqrtF* ins)
 {
-    MOZ_CRASH("visitSqrtF");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 32);
+    ARMFPRegister output(ToFloatRegister(ins->output()), 32);
+    masm.Fsqrt(output, input);
 }
 
 // FIXME: Uh, is this a static function? It looks like it is...
 template <typename T>
 ARMRegister
 toWRegister(const T* a)
 {
     return ARMRegister(ToRegister(a), 32);
@@ -701,23 +723,61 @@ void
 CodeGeneratorARM64::emitTableSwitchDispatch(MTableSwitch* mir, Register index_, Register base_)
 {
     MOZ_CRASH("emitTableSwitchDispatch");
 }
 
 void
 CodeGenerator::visitMathD(LMathD* math)
 {
-    MOZ_CRASH("visitMathD");
+    ARMFPRegister lhs(ToFloatRegister(math->lhs()), 64);
+    ARMFPRegister rhs(ToFloatRegister(math->rhs()), 64);
+    ARMFPRegister output(ToFloatRegister(math->output()), 64);
+
+    switch (math->jsop()) {
+      case JSOP_ADD:
+        masm.Fadd(output, lhs, rhs);
+        break;
+      case JSOP_SUB:
+        masm.Fsub(output, lhs, rhs);
+        break;
+      case JSOP_MUL:
+        masm.Fmul(output, lhs, rhs);
+        break;
+      case JSOP_DIV:
+        masm.Fdiv(output, lhs, rhs);
+        break;
+      default:
+        MOZ_CRASH("unexpected opcode");
+    }
 }
 
 void
 CodeGenerator::visitMathF(LMathF* math)
 {
-    MOZ_CRASH("visitMathF");
+    ARMFPRegister lhs(ToFloatRegister(math->lhs()), 32);
+    ARMFPRegister rhs(ToFloatRegister(math->rhs()), 32);
+    ARMFPRegister output(ToFloatRegister(math->output()), 32);
+
+    switch (math->jsop()) {
+      case JSOP_ADD:
+        masm.Fadd(output, lhs, rhs);
+        break;
+      case JSOP_SUB:
+        masm.Fsub(output, lhs, rhs);
+        break;
+      case JSOP_MUL:
+        masm.Fmul(output, lhs, rhs);
+        break;
+      case JSOP_DIV:
+        masm.Fdiv(output, lhs, rhs);
+        break;
+      default:
+        MOZ_CRASH("unexpected opcode");
+    }
 }
 
 void
 CodeGenerator::visitFloor(LFloor* lir)
 {
     FloatRegister input = ToFloatRegister(lir->input());
     Register output = ToRegister(lir->output());
 
@@ -789,39 +849,39 @@ CodeGenerator::visitClzI(LClzI* lir)
     ARMRegister input = toWRegister(lir->input());
     ARMRegister output = toWRegister(lir->output());
     masm.Clz(output, input);
 }
 
 void
 CodeGenerator::visitCtzI(LCtzI* lir)
 {
-    MOZ_CRASH("visitCtzI");
+    Register input = ToRegister(lir->input());
+    Register output = ToRegister(lir->output());
+    masm.ctz32(input, output, /* knownNotZero = */ false);
 }
 
 void
 CodeGeneratorARM64::emitRoundDouble(FloatRegister src, Register dest, Label* fail)
 {
     MOZ_CRASH("CodeGeneratorARM64::emitRoundDouble");
 }
 
 void
 CodeGenerator::visitTruncateDToInt32(LTruncateDToInt32* ins)
 {
-    MOZ_CRASH("visitTruncateDToInt32");
+    emitTruncateDouble(ToFloatRegister(ins->input()), ToRegister(ins->output()), ins->mir());
 }
 
 void
 CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins)
 {
-    MOZ_CRASH("visitTruncateFToInt32");
+    emitTruncateFloat32(ToFloatRegister(ins->input()), ToRegister(ins->output()), ins->mir());
 }
 
-static const uint32_t FrameSizes[] = { 128, 256, 512, 1024 };
-
 FrameSizeClass
 FrameSizeClass::FromDepth(uint32_t frameDepth)
 {
     return FrameSizeClass::None();
 }
 
 FrameSizeClass
 FrameSizeClass::ClassLimit()
@@ -938,22 +998,16 @@ CodeGenerator::visitDouble(LDouble* ins)
 void
 CodeGenerator::visitFloat32(LFloat32* ins)
 {
     ARMFPRegister output(ToFloatRegister(ins->getDef(0)), 32);
     masm.Fmov(output, ins->getFloat());
 }
 
 void
-CodeGeneratorARM64::splitTagForTest(const ValueOperand& value, ScratchTagScope& tag)
-{
-    MOZ_CRASH("splitTagForTest");
-}
-
-void
 CodeGenerator::visitTestDAndBranch(LTestDAndBranch* test)
 {
     MOZ_CRASH("visitTestDAndBranch");
 }
 
 void
 CodeGenerator::visitTestFAndBranch(LTestFAndBranch* test)
 {
@@ -1006,23 +1060,61 @@ CodeGenerator::visitCompareFAndBranch(LC
 
     masm.compareFloat(doubleCond, left, right);
     emitBranch(cond, comp->ifTrue(), comp->ifFalse());
 }
 
 void
 CodeGenerator::visitCompareB(LCompareB* lir)
 {
-    MOZ_CRASH("visitCompareB");
+    MCompare* mir = lir->mir();
+    const ValueOperand lhs = ToValue(lir, LCompareB::Lhs);
+    const LAllocation* rhs = lir->rhs();
+    const Register output = ToRegister(lir->output());
+    const Assembler::Condition cond = JSOpToCondition(mir->compareType(), mir->jsop());
+
+    vixl::UseScratchRegisterScope temps(&masm.asVIXL());
+    const Register scratch = temps.AcquireX().asUnsized();
+
+    MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
+
+    // Load boxed boolean into scratch.
+    if (rhs->isConstant()) {
+        masm.moveValue(rhs->toConstant()->toJSValue(), ValueOperand(scratch));
+    } else {
+        masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
+    }
+
+    // Compare the entire Value.
+    masm.cmpPtrSet(cond, lhs.valueReg(), scratch, output);
 }
 
 void
 CodeGenerator::visitCompareBAndBranch(LCompareBAndBranch* lir)
 {
-    MOZ_CRASH("visitCompareBAndBranch");
+    MCompare* mir = lir->cmpMir();
+    const ValueOperand lhs = ToValue(lir, LCompareBAndBranch::Lhs);
+    const LAllocation* rhs = lir->rhs();
+    const Assembler::Condition cond = JSOpToCondition(mir->compareType(), mir->jsop());
+
+    vixl::UseScratchRegisterScope temps(&masm.asVIXL());
+    const Register scratch = temps.AcquireX().asUnsized();
+
+    MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
+
+    // Load boxed boolean into scratch.
+    if (rhs->isConstant()) {
+        masm.moveValue(rhs->toConstant()->toJSValue(), ValueOperand(scratch));
+    } else {
+        masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
+    }
+
+    // Compare the entire Value.
+    masm.cmpPtr(lhs.valueReg(), scratch);
+    emitBranch(cond, lir->ifTrue(), lir->ifFalse());
 }
 
 void
 CodeGenerator::visitCompareBitwise(LCompareBitwise* lir)
 {
     MCompare* mir = lir->mir();
     Assembler::Condition cond = JSOpToCondition(mir->compareType(), mir->jsop());
     const ValueOperand lhs = ToValue(lir, LCompareBitwise::LhsInput);
@@ -1047,52 +1139,81 @@ CodeGenerator::visitCompareBitwiseAndBra
 
     masm.cmpPtr(lhs.valueReg(), rhs.valueReg());
     emitBranch(cond, lir->ifTrue(), lir->ifFalse());
 }
 
 void
 CodeGenerator::visitBitAndAndBranch(LBitAndAndBranch* baab)
 {
-    MOZ_CRASH("visitBitAndAndBranch");
+    if (baab->right()->isConstant()) {
+        masm.Tst(toWRegister(baab->left()), Operand(ToInt32(baab->right())));
+    } else {
+        masm.Tst(toWRegister(baab->left()), toWRegister(baab->right()));
+    }
+    emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse());
 }
 
 void
 CodeGenerator::visitWasmUint32ToDouble(LWasmUint32ToDouble* lir)
 {
-    MOZ_CRASH("visitWasmUint32ToDouble");
+    masm.convertUInt32ToDouble(ToRegister(lir->input()), ToFloatRegister(lir->output()));
 }
 
 void
 CodeGenerator::visitWasmUint32ToFloat32(LWasmUint32ToFloat32* lir)
 {
-    MOZ_CRASH("visitWasmUint32ToFloat32");
+    masm.convertUInt32ToFloat32(ToRegister(lir->input()), ToFloatRegister(lir->output()));
 }
 
 void
 CodeGenerator::visitNotI(LNotI* ins)
 {
-    MOZ_CRASH("visitNotI");
+    ARMRegister input = toWRegister(ins->input());
+    ARMRegister output = toWRegister(ins->output());
+
+    masm.Cmp(input, ZeroRegister32);
+    masm.Cset(output, Assembler::Zero);
 }
 
 //        NZCV
 // NAN -> 0011
 // ==  -> 0110
 // <   -> 1000
 // >   -> 0010
 void
 CodeGenerator::visitNotD(LNotD* ins)
 {
-    MOZ_CRASH("visitNotD");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 64);
+    ARMRegister output = toWRegister(ins->output());
+
+    // Set output to 1 if input compares equal to 0.0, else 0.
+    masm.Fcmp(input, 0.0);
+    masm.Cset(output, Assembler::Equal);
+
+    // Comparison with NaN sets V in the NZCV register.
+    // If the input was NaN, output must now be zero, so it can be incremented.
+    // The instruction is read: "output = if NoOverflow then output else 0+1".
+    masm.Csinc(output, output, ZeroRegister32, Assembler::NoOverflow);
 }
 
 void
 CodeGenerator::visitNotF(LNotF* ins)
 {
-    MOZ_CRASH("visitNotF");
+    ARMFPRegister input(ToFloatRegister(ins->input()), 32);
+    ARMRegister output = toWRegister(ins->output());
+
+    // Set output to 1 input compares equal to 0.0, else 0.
+    masm.Fcmp(input, 0.0);
+    masm.Cset(output, Assembler::Equal);
+
+    // Comparison with NaN sets V in the NZCV register.
+    // If the input was NaN, output must now be zero, so it can be incremented.
+    // The instruction is read: "output = if NoOverflow then output else 0+1".
+    masm.Csinc(output, output, ZeroRegister32, Assembler::NoOverflow);
 }
 
 void
 CodeGeneratorARM64::storeElementTyped(const LAllocation* value, MIRType valueType,
                                       MIRType elementType, Register elements,
                                       const LAllocation* index)
 {
     MOZ_CRASH("CodeGeneratorARM64::storeElementTyped");
@@ -1173,35 +1294,47 @@ void
 CodeGenerator::visitUMod(LUMod* ins)
 {
     MOZ_CRASH("visitUMod");
 }
 
 void
 CodeGenerator::visitEffectiveAddress(LEffectiveAddress* ins)
 {
-    MOZ_CRASH("visitEffectiveAddress");
+    const MEffectiveAddress* mir = ins->mir();
+    const ARMRegister base = toXRegister(ins->base());
+    const ARMRegister index = toXRegister(ins->index());
+    const ARMRegister output = toXRegister(ins->output());
+
+    masm.Add(output, base, Operand(index, vixl::LSL, mir->scale()));
+    masm.Add(output, output, Operand(mir->displacement()));
 }
 
 void
 CodeGenerator::visitNegI(LNegI* ins)
 {
-    MOZ_CRASH("visitNegI");
+    const ARMRegister input = toWRegister(ins->input());
+    const ARMRegister output = toWRegister(ins->output());
+    masm.Neg(output, input);
 }
 
 void
 CodeGenerator::visitNegD(LNegD* ins)
 {
-    MOZ_CRASH("visitNegD");
+    const ARMFPRegister input(ToFloatRegister(ins->input()), 64);
+    const ARMFPRegister output(ToFloatRegister(ins->input()), 64);
+    masm.Fneg(output, input);
 }
 
 void
 CodeGenerator::visitNegF(LNegF* ins)
 {
-    MOZ_CRASH("visitNegF");
+    const ARMFPRegister input(ToFloatRegister(ins->input()), 32);
+    const ARMFPRegister output(ToFloatRegister(ins->input()), 32);
+    masm.Fneg(output, input);
 }
 
 void
 CodeGenerator::visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir)
 {
     Register elements = ToRegister(lir->elements());
     AnyRegister output = ToAnyRegister(lir->output());
     Register temp = lir->temp()->isBogusTemp() ? InvalidReg : ToRegister(lir->temp());
--- a/js/src/jit/arm64/CodeGenerator-arm64.h
+++ b/js/src/jit/arm64/CodeGenerator-arm64.h
@@ -89,19 +89,16 @@ class CodeGeneratorARM64 : public CodeGe
         emitBranch(cond, ifTrue, ifFalse);
     }
 
     void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base);
 
     ValueOperand ToValue(LInstruction* ins, size_t pos);
     ValueOperand ToTempValue(LInstruction* ins, size_t pos);
 
-    // Functions for LTestVAndBranch.
-    void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag);
-
     void storeElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType,
                            Register elements, const LAllocation* index);
 
     void divICommon(MDiv* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot,
                     Label& done);
     void modICommon(MMod* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot,
                     Label& done);
 
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -127,25 +127,28 @@ LIRGeneratorARM64::lowerForALU(LInstruct
     ins->setOperand(1, ins->snapshot() ? useRegisterOrConstant(rhs) :
                                          useRegisterOrConstantAtStart(rhs));
     define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 void
 LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input)
 {
-    MOZ_CRASH("lowerForFPU");
+    ins->setOperand(0, useRegisterAtStart(input));
+    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 template <size_t Temps>
 void
 LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir,
                                MDefinition* lhs, MDefinition* rhs)
 {
-    MOZ_CRASH("lowerForFPU");
+    ins->setOperand(0, useRegisterAtStart(lhs));
+    ins->setOperand(1, useRegisterAtStart(rhs));
+    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 template void LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
                                              MDefinition* lhs, MDefinition* rhs);
 template void LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, 1>* ins, MDefinition* mir,
                                              MDefinition* lhs, MDefinition* rhs);
 
 void
@@ -175,17 +178,19 @@ template void LIRGeneratorARM64::lowerFo
 template void LIRGeneratorARM64::lowerForShiftInt64(
     LInstructionHelper<INT64_PIECES, INT64_PIECES+1, 1>* ins, MDefinition* mir,
     MDefinition* lhs, MDefinition* rhs);
 
 void
 LIRGeneratorARM64::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
                                          MDefinition* lhs, MDefinition* rhs)
 {
-    MOZ_CRASH("lowerForBitAndAndBranch");
+    baab->setOperand(0, useRegisterAtStart(lhs));
+    baab->setOperand(1, useRegisterOrConstantAtStart(rhs));
+    add(baab, mir);
 }
 
 void
 LIRGeneratorARM64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
                                         LBlock* block, size_t lirIndex)
 {
     lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
 }
@@ -240,42 +245,64 @@ void
 LIRGeneratorARM64::lowerModI64(MMod* mod)
 {
     MOZ_CRASH("NYI");
 }
 
 void
 LIRGenerator::visitPowHalf(MPowHalf* ins)
 {
-    MOZ_CRASH("visitPowHalf");
+    MDefinition* input = ins->input();
+    MOZ_ASSERT(input->type() == MIRType::Double);
+    LPowHalfD* lir = new(alloc()) LPowHalfD(useRegister(input));
+    define(lir, ins);
 }
 
 LTableSwitch*
 LIRGeneratorARM64::newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
                                        MTableSwitch* tableswitch)
 {
-    MOZ_CRASH("newLTableSwitch");
+    return new(alloc()) LTableSwitch(in, inputCopy, tableswitch);
 }
 
 LTableSwitchV*
 LIRGeneratorARM64::newLTableSwitchV(MTableSwitch* tableswitch)
 {
-    MOZ_CRASH("newLTableSwitchV");
+    MOZ_CRASH("NYI");
 }
 
 void
 LIRGeneratorARM64::lowerUrshD(MUrsh* mir)
 {
-    MOZ_CRASH("lowerUrshD");
+    MDefinition* lhs = mir->lhs();
+    MDefinition* rhs = mir->rhs();
+
+    MOZ_ASSERT(lhs->type() == MIRType::Int32);
+    MOZ_ASSERT(rhs->type() == MIRType::Int32);
+
+    LUrshD* lir = new(alloc()) LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp());
+    define(lir, mir);
 }
 
 void
 LIRGenerator::visitWasmNeg(MWasmNeg* ins)
 {
-    MOZ_CRASH("visitWasmNeg");
+    switch (ins->type()) {
+      case MIRType::Int32:
+        define(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins);
+        break;
+      case MIRType::Float32:
+        define(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
+        break;
+      case MIRType::Double:
+        define(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
+        break;
+      default:
+        MOZ_CRASH("unexpected type");
+    }
 }
 
 void
 LIRGenerator::visitWasmSelect(MWasmSelect* ins)
 {
     MOZ_CRASH("visitWasmSelect");
 }
 
@@ -361,25 +388,30 @@ void
 LIRGenerator::visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
 LIRGenerator::visitSubstr(MSubstr* ins)
 {
-    MOZ_CRASH("visitSubstr");
+    LSubstr* lir = new(alloc()) LSubstr(useRegister(ins->string()),
+                                        useRegister(ins->begin()),
+                                        useRegister(ins->length()),
+                                        temp(),
+                                        temp(),
+                                        temp());
+    define(lir, ins);
+    assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitRandom(MRandom* ins)
 {
-    LRandom *lir = new(alloc()) LRandom(temp(),
-                                        temp(),
-                                        temp());
+    LRandom* lir = new(alloc()) LRandom(temp(), temp(), temp());
     defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
 }
 
 void
 LIRGenerator::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins)
 {
     MOZ_CRASH("NYI");
 }
deleted file mode 100644
index 5b6d505c434d6a64ca5239ca0ce4bdd67085bbb7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/multipart/unit/let_in_fun.js
+++ /dev/null
@@ -1,3 +0,0 @@
-function test() {
-    let limit = 1;
-}
--- a/js/src/jsapi-tests/testBinTokenReaderTester.cpp
+++ b/js/src/jsapi-tests/testBinTokenReaderTester.cpp
@@ -13,17 +13,19 @@
 #elif defined(XP_UNIX)
 #include <fcntl.h>
 #include <unistd.h>
 #endif // defined (XP_WIN) || defined (XP_UNIX)
 
 #include "mozilla/Maybe.h"
 
 #include "frontend/BinTokenReaderTester.h"
+#include "frontend/ErrorReporter.h"
 
+#include "js/UniquePtr.h"
 #include "js/Vector.h"
 
 #include "jsapi-tests/tests.h"
 
 using mozilla::Maybe;
 
 using Tokenizer = js::frontend::BinTokenReaderTester;
 using Chars = js::frontend::BinTokenReaderTester::Chars;
@@ -102,16 +104,71 @@ void exitJsDirectory() {
     if (SetCurrentDirectory(gJsDirectory) == 0) {
         MOZ_CRASH("Could not return to original directory");
     }
     gJsDirectory[0] = 0;
 }
 
 #endif // defined(XP_UNIX) || defined(XP_WIN)
 
+// An dummy error reporter that does nothing, which is requred by
+// BinTokenReaderTester ctor.
+// These testcases don't test error case, so methods that is related to
+// error reporting crashes when called.
+class DummyErrorReporter : public js::frontend::ErrorReporter
+{
+    const JS::CompileOptions options_;
+
+  public:
+    explicit DummyErrorReporter(JSContext* cx)
+      : options_(cx)
+    {}
+
+    virtual const JS::ReadOnlyCompileOptions& options() const override {
+        return options_;
+    }
+
+    virtual void lineAndColumnAt(size_t offset, uint32_t* line, uint32_t* column) const override {
+        *line = 0;
+        *column = 0;
+    }
+    virtual void currentLineAndColumn(uint32_t* line, uint32_t* column) const override {
+        *line = 0;
+        *column = 0;
+    }
+    virtual bool isOnThisLine(size_t offset, uint32_t lineNum, bool *onThisLine) const override {
+        *onThisLine = true;
+        return true;
+    }
+    virtual uint32_t lineAt(size_t offset) const override {
+        return 0;
+    }
+    virtual uint32_t columnAt(size_t offset) const override {
+        return 0;
+    }
+
+    virtual bool hasTokenizationStarted() const override {
+        return true;
+    }
+    virtual void reportErrorNoOffsetVA(unsigned errorNumber, va_list args) override {
+        MOZ_CRASH("shouldn't be used in test");
+    }
+    virtual const char* getFilename() const override {
+        return "dummy filename";
+    }
+
+    virtual void errorAtVA(uint32_t offset, unsigned errorNumber, va_list* args) override {
+        MOZ_CRASH("shouldn't be used in test");
+    }
+    virtual bool reportExtraWarningErrorNumberVA(js::UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned errorNumber, va_list* args) override {
+        MOZ_CRASH("shouldn't be used in test");
+        return false;
+    }
+};
+
 void readFull(const char* path, js::Vector<uint8_t>& buf) {
     enterJsDirectory();
     buf.shrinkTo(0);
     FILE* in = fopen(path, "rb");
     if (!in) {
         MOZ_CRASH_UNSAFE_PRINTF("Could not open %s: %s", path, strerror(errno));
     }
 
@@ -135,66 +192,70 @@ void readFull(const char* path, js::Vect
 }
 
 
 // Reading a simple string.
 BEGIN_TEST(testBinTokenReaderTesterSimpleString)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-simple-string.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     Chars found(cx);
     CHECK(tokenizer.readChars(found).isOk());
 
     CHECK(Tokenizer::equals(found, "simple string")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterSimpleString)
 
 // Reading a string with embedded 0.
 BEGIN_TEST(testBinTokenReaderTesterStringWithEscapes)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-string-with-escapes.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     Chars found(cx);
     CHECK(tokenizer.readChars(found).isOk());
 
     CHECK(Tokenizer::equals(found, "string with escapes \0\1\0")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterStringWithEscapes)
 
 // Reading an empty untagged tuple
 BEGIN_TEST(testBinTokenReaderTesterEmptyUntaggedTuple)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-empty-untagged-tuple.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         Tokenizer::AutoTuple guard(tokenizer);
         CHECK(tokenizer.enterUntaggedTuple(guard).isOk());
         CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterEmptyUntaggedTuple)
 
 // Reading a untagged tuple with two strings
 BEGIN_TEST(testBinTokenReaderTesterTwoStringsInTuple)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-trivial-untagged-tuple.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         Tokenizer::AutoTuple guard(tokenizer);
         CHECK(tokenizer.enterUntaggedTuple(guard).isOk());
 
         Chars found_0(cx);
         CHECK(tokenizer.readChars(found_0).isOk());
         CHECK(Tokenizer::equals(found_0, "foo")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
@@ -210,17 +271,18 @@ BEGIN_TEST(testBinTokenReaderTesterTwoSt
 }
 END_TEST(testBinTokenReaderTesterTwoStringsInTuple)
 
 // Reading a tagged tuple `Pattern { id: "foo", value: 3.1415}`
 BEGIN_TEST(testBinTokenReaderTesterSimpleTaggedTuple)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-simple-tagged-tuple.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         js::frontend::BinKind tag;
         Tokenizer::BinFields fields(cx);
         Tokenizer::AutoTaggedTuple guard(tokenizer);
         CHECK(tokenizer.enterTaggedTuple(tag, fields, guard).isOk());
 
         CHECK(tag == js::frontend::BinKind::BindingIdentifier);
@@ -244,17 +306,18 @@ BEGIN_TEST(testBinTokenReaderTesterSimpl
 END_TEST(testBinTokenReaderTesterSimpleTaggedTuple)
 
 
 // Reading an empty list
 BEGIN_TEST(testBinTokenReaderTesterEmptyList)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-empty-list.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         uint32_t length;
         Tokenizer::AutoList guard(tokenizer);
         CHECK(tokenizer.enterList(length, guard).isOk());
 
         CHECK(length == 0);
         CHECK(guard.done().isOk());
@@ -264,17 +327,18 @@ BEGIN_TEST(testBinTokenReaderTesterEmpty
 }
 END_TEST(testBinTokenReaderTesterEmptyList)
 
 // Reading `["foo", "bar"]`
 BEGIN_TEST(testBinTokenReaderTesterSimpleList)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-trivial-list.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         uint32_t length;
         Tokenizer::AutoList guard(tokenizer);
         CHECK(tokenizer.enterList(length, guard).isOk());
 
         CHECK(length == 2);
 
@@ -294,17 +358,18 @@ BEGIN_TEST(testBinTokenReaderTesterSimpl
 END_TEST(testBinTokenReaderTesterSimpleList)
 
 
 // Reading `[["foo", "bar"]]`
 BEGIN_TEST(testBinTokenReaderTesterNestedList)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-nested-lists.binjs", contents);
-    Tokenizer tokenizer(cx, nullptr, contents);
+    DummyErrorReporter reporter(cx);
+    Tokenizer tokenizer(cx, &reporter, contents);
 
     {
         uint32_t outerLength;
         Tokenizer::AutoList outerGuard(tokenizer);
         CHECK(tokenizer.enterList(outerLength, outerGuard).isOk());
         CHECK_EQUAL(outerLength, (uint32_t)1);
 
         {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -931,17 +931,17 @@ RunFile(JSContext* cx, const char* filen
         }
     }
     return true;
 }
 
 #if defined(JS_BUILD_BINAST)
 
 static MOZ_MUST_USE bool
-RunBinAST(JSContext* cx, const char* filename, FILE* file)
+RunBinAST(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
 {
     RootedScript script(cx);
 
     {
         CompileOptions options(cx);
         options.setFileAndLine(filename, 0)
                .setIsRunOnce(true)
                .setNoScriptRval(true);
@@ -951,16 +951,20 @@ RunBinAST(JSContext* cx, const char* fil
             return false;
         }
     }
 
     if (!RegisterScriptPathWithModuleLoader(cx, script, filename)) {
         return false;
     }
 
+    if (compileOnly) {
+        return true;
+    }
+
     return JS_ExecuteScript(cx, script);
 }
 
 #endif // JS_BUILD_BINAST
 
 static bool
 InitModuleLoader(JSContext* cx)
 {
@@ -1405,17 +1409,17 @@ Process(JSContext* cx, const char* filen
             break;
           case FileModule:
             if (!RunModule(cx, filename, file, compileOnly)) {
                 return false;
             }
             break;
 #if defined(JS_BUILD_BINAST)
           case FileBinAST:
-            if (!RunBinAST(cx, filename, file)) {
+            if (!RunBinAST(cx, filename, file, compileOnly)) {
                 return false;
             }
             break;
 #endif // JS_BUILD_BINAST
           default:
             MOZ_CRASH("Impossible FileKind!");
         }
     } else {
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -2195,16 +2195,23 @@ JSContext::addPendingCompileError(js::Co
     if (!parseTask->errors.append(std::move(errorPtr))) {
         ReportOutOfMemory(this);
         return false;
     }
     *error = parseTask->errors.back().get();
     return true;
 }
 
+bool
+JSContext::isCompileErrorPending() const
+{
+    ParseTask* parseTask = helperThread()->parseTask();
+    return parseTask->errors.length() > 0;
+}
+
 void
 JSContext::addPendingOverRecursed()
 {
     if (helperThread()->parseTask()) {
         helperThread()->parseTask()->overRecursed = true;
     }
 }
 
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -359,16 +359,18 @@ struct JSContext : public JS::RootingCon
         atomMarking().markAtomValue(this, value);
     }
 
     // Methods specific to any HelperThread for the context.
     bool addPendingCompileError(js::CompileError** err);
     void addPendingOverRecursed();
     void addPendingOutOfMemory();
 
+    bool isCompileErrorPending() const;
+
     JSRuntime* runtime() { return runtime_; }
     const JSRuntime* runtime() const { return runtime_; }
 
     static size_t offsetOfRealm() {
         return offsetof(JSContext, realm_);
     }
 
     friend class JS::AutoSaveExceptionState;
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -2374,37 +2374,16 @@ ScriptSource::performXDR(XDRState<mode>*
 
     if ((hasSource || hasBinSource) && !sourceRetrievable_) {
         uint32_t uncompressedLength = 0;
         if (mode == XDR_ENCODE) {
             uncompressedLength = length();
         }
         MOZ_TRY(xdr->codeUint32(&uncompressedLength));
 
-        // A compressed length of 0 indicates source is uncompressed (or is
-        // BinAST if |hasBinSource|).
-        uint32_t compressedLength;
-        if (mode == XDR_ENCODE) {
-            compressedLength = compressedLengthOrZero();
-        }
-        MOZ_TRY(xdr->codeUint32(&compressedLength));
-
-        uint8_t srcCharSize;
-        if (mode == XDR_ENCODE) {
-            srcCharSize = sourceCharSize();
-        }
-        MOZ_TRY(xdr->codeUint8(&srcCharSize));
-
-        if (srcCharSize != 1 && srcCharSize != 2) {
-            // Fail in debug, but only soft-fail in release, if the source-char
-            // size is invalid.
-            MOZ_ASSERT_UNREACHABLE("bad XDR source chars size");
-            return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
-        }
-
         if (hasBinSource) {
             if (mode == XDR_DECODE) {
 #if defined(JS_BUILD_BINAST)
                 auto bytes =
                     xdr->cx()->template make_pod_array<char>(Max<size_t>(uncompressedLength, 1));
                 if (!bytes) {
                     return xdr->fail(JS::TranscodeResult_Throw);
                 }
@@ -2416,41 +2395,63 @@ ScriptSource::performXDR(XDRState<mode>*
 #else
                 MOZ_ASSERT(mode != XDR_ENCODE);
                 return xdr->fail(JS::TranscodeResult_Throw);
 #endif /* JS_BUILD_BINAST */
             } else {
                 void* bytes = binASTData();
                 MOZ_TRY(xdr->codeBytes(bytes, uncompressedLength));
             }
-        } else if (compressedLength) {
-            if (mode == XDR_DECODE) {
-                // Compressed data is always single-byte chars.
-                auto bytes = xdr->cx()->template make_pod_array<char>(compressedLength);
-                if (!bytes) {
-                    return xdr->fail(JS::TranscodeResult_Throw);
-                }
-                MOZ_TRY(xdr->codeBytes(bytes.get(), compressedLength));
-
-                if (!(srcCharSize == 1
-                      ? setCompressedSource<Utf8Unit>(xdr->cx(), std::move(bytes),
-                                                      compressedLength, uncompressedLength)
-                      : setCompressedSource<char16_t>(xdr->cx(), std::move(bytes),
-                                                      compressedLength, uncompressedLength)))
-                {
-                    return xdr->fail(JS::TranscodeResult_Throw);
+        } else {
+            // A compressed length of 0 indicates source is uncompressed
+            uint32_t compressedLength;
+            if (mode == XDR_ENCODE) {
+                compressedLength = compressedLengthOrZero();
+            }
+            MOZ_TRY(xdr->codeUint32(&compressedLength));
+
+            uint8_t srcCharSize;
+            if (mode == XDR_ENCODE) {
+                srcCharSize = sourceCharSize();
+            }
+            MOZ_TRY(xdr->codeUint8(&srcCharSize));
+
+            if (srcCharSize != 1 && srcCharSize != 2) {
+                // Fail in debug, but only soft-fail in release, if the source-char
+                // size is invalid.
+                MOZ_ASSERT_UNREACHABLE("bad XDR source chars size");
+                return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
+            }
+
+            if (compressedLength) {
+                if (mode == XDR_DECODE) {
+                    // Compressed data is always single-byte chars.
+                    auto bytes = xdr->cx()->template make_pod_array<char>(compressedLength);
+                    if (!bytes) {
+                        return xdr->fail(JS::TranscodeResult_Throw);
+                    }
+                    MOZ_TRY(xdr->codeBytes(bytes.get(), compressedLength));
+
+                    if (!(srcCharSize == 1
+                          ? setCompressedSource<Utf8Unit>(xdr->cx(), std::move(bytes),
+                                                          compressedLength, uncompressedLength)
+                          : setCompressedSource<char16_t>(xdr->cx(), std::move(bytes),
+                                                          compressedLength, uncompressedLength)))
+                    {
+                        return xdr->fail(JS::TranscodeResult_Throw);
+                    }
+                } else {
+                    void* bytes = srcCharSize == 1
+                                  ? compressedData<Utf8Unit>()
+                                  : compressedData<char16_t>();
+                    MOZ_TRY(xdr->codeBytes(bytes, compressedLength));
                 }
             } else {
-                void* bytes = srcCharSize == 1
-                              ? compressedData<Utf8Unit>()
-                              : compressedData<char16_t>();
-                MOZ_TRY(xdr->codeBytes(bytes, compressedLength));
+                MOZ_TRY(xdrUncompressedSource(xdr, srcCharSize, uncompressedLength));
             }
-        } else {
-            MOZ_TRY(xdrUncompressedSource(xdr, srcCharSize, uncompressedLength));
         }
 
         uint8_t hasMetadata = !!binASTMetadata_;
         MOZ_TRY(xdr->codeUint8(&hasMetadata));
         if (hasMetadata) {
 #if defined(JS_BUILD_BINAST)
             uint32_t numBinKinds;
             uint32_t numStrings;
@@ -2459,22 +2460,23 @@ ScriptSource::performXDR(XDRState<mode>*
                 numStrings = binASTMetadata_->numStrings();
             }
             MOZ_TRY(xdr->codeUint32(&numBinKinds));
             MOZ_TRY(xdr->codeUint32(&numStrings));
 
             if (mode == XDR_DECODE) {
                 // Use calloc, since we're storing this immediately, and filling it might GC, to
                 // avoid marking bogus atoms.
-                setBinASTSourceMetadata(
-                    static_cast<frontend::BinASTSourceMetadata*>(
-                        js_calloc(frontend::BinASTSourceMetadata::totalSize(numBinKinds, numStrings))));
-                if (!binASTMetadata_) {
+                auto metadata = static_cast<frontend::BinASTSourceMetadata*>(
+                    js_calloc(frontend::BinASTSourceMetadata::totalSize(numBinKinds, numStrings)));
+                if (!metadata) {
                     return xdr->fail(JS::TranscodeResult_Throw);
                 }
+                new (metadata) frontend::BinASTSourceMetadata(numBinKinds, numStrings);
+                setBinASTSourceMetadata(metadata);
             }
 
             for (uint32_t i = 0; i < numBinKinds; i++) {
                 frontend::BinKind* binKindBase = binASTMetadata_->binKindBase();
                 MOZ_TRY(xdr->codeEnum32(&binKindBase[i]));
             }
 
             RootedAtom atom(xdr->cx());
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -371,16 +371,24 @@ WebrtcVideoConduit::SendStreamStatistics
   mJitterMs = ind->second.rtcp_stats.jitter /
       (webrtc::kVideoPayloadTypeFrequency / 1000);
   mPacketsLost = ind->second.rtcp_stats.packets_lost;
   mBytesReceived = ind->second.rtp_stats.MediaPayloadBytes();
   mPacketsReceived = ind->second.rtp_stats.transmitted.packets;
 }
 
 uint32_t
+WebrtcVideoConduit::ReceiveStreamStatistics::BytesSent() const
+{
+  ASSERT_ON_THREAD(mStatsThread);
+
+  return mBytesSent;
+}
+
+uint32_t
 WebrtcVideoConduit::ReceiveStreamStatistics::DiscardedPackets() const
 {
   ASSERT_ON_THREAD(mStatsThread);
 
   return mDiscardedPackets;
 }
 
 uint32_t
@@ -403,38 +411,48 @@ uint32_t
 WebrtcVideoConduit::ReceiveStreamStatistics::PacketsLost() const
 {
   ASSERT_ON_THREAD(mStatsThread);
 
   return mPacketsLost;
 }
 
 uint32_t
+WebrtcVideoConduit::ReceiveStreamStatistics::PacketsSent() const
+{
+  ASSERT_ON_THREAD(mStatsThread);
+
+  return mPacketsSent;
+}
+
+uint32_t
 WebrtcVideoConduit::ReceiveStreamStatistics::Ssrc() const
 {
   ASSERT_ON_THREAD(mStatsThread);
 
   return mSsrc;
 }
 
 void
 WebrtcVideoConduit::ReceiveStreamStatistics::Update(
   const webrtc::VideoReceiveStream::Stats& aStats)
 {
   ASSERT_ON_THREAD(mStatsThread);
 
   CSFLogVerbose(LOGTAG, "%s ", __FUNCTION__);
   StreamStatistics::Update(aStats.decode_frame_rate, aStats.total_bitrate_bps,
                            aStats.rtcp_packet_type_counts);
+  mBytesSent = aStats.rtcp_sender_octets_sent;
   mDiscardedPackets = aStats.discarded_packets;
   mFramesDecoded =
     aStats.frame_counts.key_frames + aStats.frame_counts.delta_frames;
   mJitterMs =
     aStats.rtcp_stats.jitter / (webrtc::kVideoPayloadTypeFrequency / 1000);
   mPacketsLost = aStats.rtcp_stats.packets_lost;
+  mPacketsSent = aStats.rtcp_sender_packets_sent;
   mSsrc = aStats.ssrc;
 }
 
 /**
  * Factory Method for VideoConduit
  */
 RefPtr<VideoSessionConduit>
 VideoSessionConduit::Create(
@@ -1292,24 +1310,23 @@ bool
 WebrtcVideoConduit::GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
                                         unsigned int* packetsSent,
                                         uint64_t* bytesSent)
 {
   ASSERT_ON_THREAD(mStsThread);
 
   CSFLogVerbose(LOGTAG, "%s for VideoConduit:%p", __FUNCTION__, this);
 
-  if (!mRecvStream) {
+  if (!mRecvStreamStats.Active()) {
     return false;
   }
 
-  webrtc::VideoReceiveStream::Stats stats = mRecvStream->GetStats();
   *timestamp = webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
-  *packetsSent = stats.rtcp_sender_packets_sent;
-  *bytesSent = stats.rtcp_sender_octets_sent;
+  *packetsSent = mRecvStreamStats.PacketsSent();
+  *bytesSent = mRecvStreamStats.BytesSent();
   return true;
 }
 
 MediaConduitErrorCode
 WebrtcVideoConduit::InitMain()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -392,33 +392,37 @@ private:
   /**
    * Statistics for receiving streams. Single threaded.
    */
   class ReceiveStreamStatistics : public StreamStatistics {
   public:
     explicit ReceiveStreamStatistics(nsCOMPtr<nsIEventTarget> aStatsThread)
       : StreamStatistics(std::forward<nsCOMPtr<nsIEventTarget>>(aStatsThread))
     {}
+    uint32_t BytesSent() const;
     /**
      * Returns the number of discarded packets
      */
     uint32_t DiscardedPackets() const;
     /**
      * Returns the number of frames decoded
      */
     uint32_t FramesDecoded() const;
     uint32_t JitterMs() const;
     uint32_t PacketsLost() const;
+    uint32_t PacketsSent() const;
     uint32_t Ssrc() const;
     void Update(const webrtc::VideoReceiveStream::Stats& aStats);
   private:
+    uint32_t mBytesSent = 0;
     uint32_t mDiscardedPackets = 0;
     uint32_t mFramesDecoded = 0;
     uint32_t mJitterMs = 0;
     uint32_t mPacketsLost = 0;
+    uint32_t mPacketsSent = 0;
     uint32_t mSsrc = 0;
   };
 
   /**
    * Stores encoder configuration information and produces
    * a VideoEncoderConfig from it.
    */
   class VideoEncoderConfigBuilder {
--- a/mfbt/Array.h
+++ b/mfbt/Array.h
@@ -22,17 +22,17 @@ template<typename T, size_t Length>
 class Array
 {
   T mArr[Length];
 
 public:
   Array() {}
 
   template <typename... Args>
-  MOZ_IMPLICIT Array(Args&&... aArgs)
+  MOZ_IMPLICIT constexpr Array(Args&&... aArgs)
     : mArr{std::forward<Args>(aArgs)...}
   {
     static_assert(sizeof...(aArgs) == Length,
                   "The number of arguments should be equal to the template parameter Length");
   }
 
   T& operator[](size_t aIndex)
   {
--- a/mfbt/EnumeratedArray.h
+++ b/mfbt/EnumeratedArray.h
@@ -50,17 +50,17 @@ private:
   typedef Array<ValueType, kSize> ArrayType;
 
   ArrayType mArray;
 
 public:
   EnumeratedArray() {}
 
   template <typename... Args>
-  MOZ_IMPLICIT EnumeratedArray(Args&&... aArgs)
+  MOZ_IMPLICIT constexpr EnumeratedArray(Args&&... aArgs)
     : mArray{std::forward<Args>(aArgs)...}
   {}
 
   explicit EnumeratedArray(const EnumeratedArray& aOther)
   {
     for (size_t i = 0; i < kSize; i++) {
       mArray[i] = aOther.mArray[i];
     }
--- a/security/manager/ssl/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/ssl/nsSecureBrowserUIImpl.cpp
@@ -149,18 +149,21 @@ nsSecureBrowserUIImpl::CheckForBlockedCo
     if (!docShell) {
       return;
     }
   }
 
   mOldState = mState;
 
   // Has mixed content been loaded or blocked in nsMixedContentBlocker?
-  // This only applies to secure documents.
-  if (mState & STATE_IS_SECURE) {
+  // This only applies to secure documents even if they're affected by mixed
+  // content blocking in which case the STATE_IS_BROKEN bit would be set rather
+  // than STATE_IS_SECURE.
+  if (((mState & STATE_IS_SECURE) != 0) ||
+      ((mState & STATE_IS_BROKEN) != 0)) {
     if (docShell->GetHasMixedActiveContentLoaded()) {
       mState |= STATE_IS_BROKEN | STATE_LOADED_MIXED_ACTIVE_CONTENT;
       mState &= ~STATE_IS_SECURE;
       mState &= ~STATE_SECURE_HIGH;
     }
 
     if (docShell->GetHasMixedDisplayContentLoaded()) {
       mState |= STATE_IS_BROKEN | STATE_LOADED_MIXED_DISPLAY_CONTENT;
--- a/testing/raptor/raptor/raptor.py
+++ b/testing/raptor/raptor/raptor.py
@@ -277,17 +277,19 @@ class Raptor(object):
             # if using host localhost, 127.0.0.1.
             if self.config['app'] == "chrome" and test.get('playback', None) is not None:
                 chrome_args = [
                     '--proxy-server="http=127.0.0.1:8080;' +
                     'https=127.0.0.1:8080;ssl=127.0.0.1:8080"',
                     '--ignore-certificate-errors'
                 ]
                 if self.config['host'] not in ('localhost', '127.0.0.1'):
-                    chrome_args[0].replace('127.0.0.1', self.config['host'])
+                    chrome_args[0] = chrome_args[0].replace('127.0.0.1', self.config['host'])
+                if ' '.join(chrome_args) not in ' '.join(self.runner.cmdargs):
+                    self.runner.cmdargs.extend(chrome_args)
 
             self.runner.start()
             proc = self.runner.process_handler
             self.output_handler.proc = proc
 
             self.control_server.browser_proc = proc
 
             # pageload tests need to be able to access non-local connections via mitmproxy
--- a/testing/web-platform/meta/payment-request/payment-request-constructor.https.html.ini
+++ b/testing/web-platform/meta/payment-request/payment-request-constructor.https.html.ini
@@ -579,20 +579,22 @@
     expected: 
       if not e10s: FAIL
 
   [If amount.value of additionalDisplayItems is not a valid decimal monetary value, then throw a TypeError]
     expected: 
       if not e10s: FAIL
 
   [Modifier data must be JSON-serializable object (an Array in this case)]
-    expected: FAIL
+    expected:
+      if not e10s: FAIL
 
   [Modifier data must be JSON-serializable object (an Object in this case)]
-    expected: FAIL
+    expected:
+      if not e10s: FAIL
 
   [Rethrow any exceptions of JSON-serializing modifier.data]
     expected: 
       if not e10s: FAIL
 
   [If there is a selected shipping option, and requestShipping is set, then that option becomes synchronously selected]
     expected: 
       if not e10s: FAIL
--- a/testing/web-platform/mozilla/tests/binast/large-binjs.js
+++ b/testing/web-platform/mozilla/tests/binast/large-binjs.js
@@ -1,12 +1,12 @@
 // Larger JS source to exercise off-thread parsing.
 
 // List of words to bulk up output file.
-const words = [
+var words = [
     "A",
     "a",
     "aa",
     "aal",
     "aalii",
     "aam",
     "Aani",
     "aardvark",
index fb86dc59c4d9f5cb5932624f9ba1d21aeb8ea389..38dc72fac8304fc3a698410f94b40c9e12ee1b97
GIT binary patch
literal 11508
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
Rm#|Jx>>$!itx|9J{|CqI=i~qY
--- a/testing/web-platform/mozilla/tests/binast/large.js
+++ b/testing/web-platform/mozilla/tests/binast/large.js
@@ -1,12 +1,12 @@
 // Larger JS source to exercise off-thread parsing.
 
 // List of words to bulk up output file.
-const words = [
+var words = [
     "A",
     "a",
     "aa",
     "aal",
     "aalii",
     "aam",
     "Aani",
     "aardvark",
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -439,22 +439,20 @@ nsThread::AddToThreadList()
   sMaxActiveThreads = std::max(sActiveThreads, sMaxActiveThreads);
 
   ThreadList().insertBack(this);
 }
 
 void
 nsThread::MaybeRemoveFromThreadList()
 {
+  OffTheBooksMutexAutoLock mal(ThreadListMutex());
   if (isInList()) {
-    OffTheBooksMutexAutoLock mal(ThreadListMutex());
-    if (isInList()) {
-      sActiveThreads--;
-      removeFrom(ThreadList());
-    }
+    sActiveThreads--;
+    removeFrom(ThreadList());
   }
 }
 
 /*static*/ void
 nsThread::ThreadFunc(void* aArg)
 {
   using mozilla::ipc::BackgroundChild;