Merge mozilla-central to autoland a=merge on a CLOSED TREE
authorCoroiu Cristina <ccoroiu@mozilla.com>
Fri, 13 Apr 2018 19:07:42 +0300
changeset 469279 c4bee2eae27cf8476d09a2c8df9009e63a7a5d91
parent 469278 ef75b7ebedc350f8f213d7e1298f1bef35f8bf33 (current diff)
parent 469264 2243b83d2c5ca7a13b592e0fed4639657a2882f1 (diff)
child 469280 7cc86dc1bbc8fb7d935b258fe5dcebb059a323cc
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland a=merge on a CLOSED TREE
browser/components/preferences/in-content/privacy.xul
browser/locales/en-US/browser/preferences/preferences.ftl
layout/base/crashtests/372576.xul
netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
netwerk/streamconv/converters/nsTXTToHTMLConv.h
--- a/browser/base/content/test/static/browser_parsable_css.js
+++ b/browser/base/content/test/static/browser_parsable_css.js
@@ -80,22 +80,16 @@ if (!Services.prefs.getBoolPref("full-sc
 }
 
 let propNameWhitelist = [
   // These are CSS custom properties that we found a definition of but
   // no reference to.
   // Bug 1441837
   {propName: "--in-content-category-text-active",
    isFromDevTools: false},
-  // Bug 1441855
-  {propName: "--chrome-nav-buttons-background",
-   isFromDevTools: false},
-  // Bug 1441855
-  {propName: "--chrome-nav-buttons-hover-background",
-   isFromDevTools: false},
   // Bug 1441929
   {propName: "--theme-search-overlays-semitransparent",
    isFromDevTools: true},
   // Bug 1441878
   {propName: "--theme-codemirror-gutter-background",
    isFromDevTools: true},
   // These custom properties are retrieved directly from CSSOM
   // in videocontrols.xml to get pre-defined style instead of computed
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -18,17 +18,17 @@
 
 <!-- Passwords -->
 <groupbox id="passwordsGroup" orient="vertical" data-category="panePrivacy" hidden="true">
   <caption><label data-l10n-id="forms-header"/></caption>
 
   <vbox id="passwordSettings">
     <hbox id="savePasswordsBox">
       <checkbox id="savePasswords"
-                data-l10n-id="forms-remember-logins"
+                data-l10n-id="forms-ask-to-save-logins"
                 preference="signon.rememberSignons"
                 onsyncfrompreference="return gPrivacyPane.readSavePasswords();"
                 flex="1" />
       <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
       <hbox>
         <button id="passwordExceptions"
                 class="accessory-button"
                 data-l10n-id="forms-exceptions"
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -580,19 +580,19 @@ sync-fxa-privacy-notice = Privacy Notice
 
 ## Privacy Section
 
 privacy-header = Browser Privacy
 
 ## Privacy Section - Forms
 
 forms-header = Forms & Passwords
-forms-remember-logins =
-    .label = Remember logins and passwords for websites
-    .accesskey = R
+forms-ask-to-save-logins =
+    .label = Ask to save logins and passwords for websites
+    .accesskey = r
 forms-exceptions =
     .label = Exceptions…
     .accesskey = x
 forms-saved-logins =
     .label = Saved Logins…
     .accesskey = L
 forms-master-pw-use =
     .label = Use a master password
--- a/browser/themes/shared/compacttheme.inc.css
+++ b/browser/themes/shared/compacttheme.inc.css
@@ -16,18 +16,16 @@
 }
 
 :root:-moz-lwtheme-brighttext {
   /* Chrome */
   --chrome-background-color: hsl(240, 5%, 5%);
   --chrome-color: rgb(249, 249, 250);
   --chrome-secondary-background-color: hsl(240, 1%, 20%);
   --toolbox-border-bottom-color: hsla(240, 5%, 5%, .1);
-  --chrome-nav-buttons-background: hsla(240, 5%, 5%, .1);
-  --chrome-nav-buttons-hover-background: hsla(240, 5%, 5%, .15);
   --chrome-nav-bar-controls-border-color: hsla(240, 5%, 5%, .3);
   --chrome-selection-color: #fff;
   --chrome-selection-background-color: #5675B9;
 
   /* Url and search bars */
   --url-and-searchbar-background-color: rgb(71, 71, 73);
   --url-and-searchbar-color: var(--chrome-color);
   --urlbar-separator-color: #5F6670;
@@ -35,18 +33,16 @@
 
 :root:-moz-lwtheme-darktext {
   --url-and-searchbar-background-color: #fff;
 
   --chrome-background-color: #E3E4E6;
   --chrome-color: #18191a;
   --chrome-secondary-background-color: #f5f6f7;
   --toolbox-border-bottom-color: #cccccc;
-  --chrome-nav-buttons-background: #ffffff; /* --theme-body-background */
-  --chrome-nav-buttons-hover-background: #DADBDB;
   --chrome-nav-bar-controls-border-color: #ccc;
   --chrome-selection-color: #f5f7fa;
   --chrome-selection-background-color: #4c9ed9;
 }
 
 #tabbrowser-tabs:-moz-lwtheme {
   --tab-line-color: #0a84ff;
 }
--- a/config/check_vanilla_allocations.py
+++ b/config/check_vanilla_allocations.py
@@ -138,16 +138,21 @@ def main():
         # we whitelist them.
         if "_memory_" in filename:
             continue
 
         # Ignore the fuzzing code imported from m-c
         if "Fuzzer" in filename:
             continue
 
+        # Ignore the profiling pseudo-stack, since it needs to run even when
+        # SpiderMonkey's allocator isn't initialized.
+        if "ProfilingStack" in filename:
+            continue
+
         fn = m.group(2)
         if filename == 'jsutil.o':
             jsutil_cpp.add(fn)
         else:
             # An allocation is present in a non-special file.  Fail!
             fail("'" + fn + "' present in " + filename)
             # Try to give more precise information about the offending code.
             emit_line_info = True
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 36.0
+Version 37.0
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-35...release-36
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-36...release-37
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.0
 - babel-preset-react @6.24.1
 - react @16.2.0
 - react-dom @16.2.0
 - webpack @3.11.0
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -26720,49 +26720,56 @@ Object.defineProperty(exports, "__esModu
 exports.findBestMatchExpression = findBestMatchExpression;
 exports.findEmptyLines = findEmptyLines;
 exports.containsPosition = containsPosition;
 exports.findClosestFunction = findClosestFunction;
 exports.findClosestClass = findClosestClass;
 
 var _lodash = __webpack_require__(2);
 
+var _pausePoints = __webpack_require__(3622);
+
+/* 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/>. */
+
 function findBestMatchExpression(symbols, tokenPos) {
   const { memberExpressions, identifiers, literals } = symbols;
   const { line, column } = tokenPos;
 
   const members = memberExpressions.filter(({ computed }) => !computed);
 
   return [].concat(identifiers, members, literals).reduce((found, expression) => {
     const overlaps = expression.location.start.line == line && expression.location.start.column <= column && expression.location.end.column >= column;
 
     if (overlaps) {
       return expression;
     }
 
     return found;
   }, null);
-} /* 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/>. */
+}
 
 function findEmptyLines(selectedSource, pausePoints) {
-  if (!pausePoints || pausePoints.length == 0 || !selectedSource) {
+  if (!pausePoints || !selectedSource) {
     return [];
   }
 
-  const breakpoints = pausePoints.filter(point => point.types.breakpoint);
+  const pausePointsList = (0, _pausePoints.convertToList)(pausePoints);
+
+  const breakpoints = pausePointsList.filter(point => point.types.break);
   const breakpointLines = breakpoints.map(point => point.location.line);
 
   if (!selectedSource.text) {
     return [];
   }
+
   const lineCount = selectedSource.text.split("\n").length;
   const sourceLines = (0, _lodash.range)(1, lineCount + 1);
-  return (0, _lodash.without)(sourceLines, ...breakpointLines);
+  return (0, _lodash.xor)(sourceLines, breakpointLines);
 }
 
 function containsPosition(a, b) {
   const startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column;
   const endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column;
 
   return startsBefore && endsAfter;
 }
@@ -38910,37 +38917,53 @@ module.exports = reducer;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+exports.convertToList = convertToList;
 exports.formatPausePoints = formatPausePoints;
 
 var _lodash = __webpack_require__(2);
 
 function insertStrtAt(string, index, newString) {
   const start = string.slice(0, index);
   const end = string.slice(index);
   return `${start}${newString}${end}`;
 } /* 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/>. */
 
-function formatPausePoints(text, nodes) {
-  nodes = (0, _lodash.reverse)((0, _lodash.sortBy)(nodes, ["location.line", "location.column"]));
+function convertToList(pausePoints) {
+  const list = [];
+  for (let line in pausePoints) {
+    for (let column in pausePoints[line]) {
+      const point = pausePoints[line][column];
+      list.push({
+        location: { line: parseInt(line, 10), column: parseInt(column, 10) },
+        types: point
+      });
+    }
+  }
+  return list;
+}
+
+function formatPausePoints(text, pausePoints) {
+  const nodes = (0, _lodash.reverse)(convertToList(pausePoints));
   const lines = text.split("\n");
   nodes.forEach((node, index) => {
     const { line, column } = node.location;
-    const { breakpoint, stepOver } = node.types;
+    const { break: breakPoint, step } = node.types;
     const num = nodes.length - index;
-    const types = `${breakpoint ? "b" : ""}${stepOver ? "s" : ""}`;
-    lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types} ${num}*/`);
+    const types = `${breakPoint ? "b" : ""}${step ? "s" : ""}`;
+    const spacer = breakPoint || step ? " " : "";
+    lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types}${spacer}${num}*/`);
   });
 
   return lines.join("\n");
 }
 
 /***/ }),
 
 /***/ 3623:
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -21181,139 +21181,146 @@ var _ast = __webpack_require__(1375);
 var _types = __webpack_require__(2268);
 
 var t = _interopRequireWildcard(_types);
 
 var _isEqual = __webpack_require__(1127);
 
 var _isEqual2 = _interopRequireDefault(_isEqual);
 
-var _uniqBy = __webpack_require__(3624);
-
-var _uniqBy2 = _interopRequireDefault(_uniqBy);
-
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
-
-const isControlFlow = node => t.isForStatement(node) || t.isWhileStatement(node) || t.isIfStatement(node) || t.isSwitchCase(node) || t.isSwitchStatement(node);
+const isControlFlow = node => t.isForStatement(node) || t.isWhileStatement(node) || t.isIfStatement(node) || t.isSwitchCase(node) || t.isSwitchStatement(node); /* This Source Code Form is subject to the terms of the Mozilla Public
+                                                                                                                                                                 * License, v. 2.0. If a copy of the MPL was not distributed with this
+                                                                                                                                                                 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 const isAssignment = node => t.isVariableDeclarator(node) || t.isAssignmentExpression(node);
 
 const isImport = node => t.isImport(node) || t.isImportDeclaration(node);
 const isReturn = node => t.isReturnStatement(node);
 const isCall = node => t.isCallExpression(node) || t.isJSXElement(node);
 
-const inExpression = (parent, grandParent) => t.isArrayExpression(parent) || t.isObjectProperty(parent) || t.isCallExpression(parent) || t.isJSXElement(parent) || t.isJSXAttribute(grandParent) || t.isTemplateLiteral(parent);
+const inStepExpression = parent => t.isArrayExpression(parent) || t.isObjectProperty(parent) || t.isCallExpression(parent) || t.isJSXElement(parent);
+
+const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJSXAttribute(grandParent) || t.isTemplateLiteral(parent);
 
 const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
 
-function removeDuplicatePoints(state) {
-  return (0, _uniqBy2.default)(state, ({ location }) => `${location.line}-$${location.column}`);
-}
-
 function getPausePoints(sourceId) {
-  const state = [];
+  const state = {};
   (0, _ast.traverseAst)(sourceId, { enter: onEnter }, state);
-  const uniqPoints = removeDuplicatePoints(state);
-  return uniqPoints;
-}
-
+  return state;
+}
+
+/* eslint-disable complexity */
 function onEnter(node, ancestors, state) {
   const parent = ancestors[ancestors.length - 1];
+  const parentNode = parent && parent.node;
   const grandParent = ancestors[ancestors.length - 2];
   const startLocation = node.loc.start;
 
   if (isImport(node) || t.isClassDeclaration(node) || isExport(node) || t.isDebuggerStatement(node)) {
-    addPoint(state, startLocation);
+    return addStopPoint(state, startLocation);
   }
 
   if (isControlFlow(node)) {
     addEmptyPoint(state, startLocation);
 
     const test = node.test || node.discriminant;
     if (test) {
-      addPoint(state, test.loc.start);
-    }
+      addStopPoint(state, test.loc.start);
+    }
+    return;
   }
 
   if (isReturn(node)) {
     // We do not want to pause at the return and the call e.g. return foo()
     if (isCall(node.argument)) {
-      addEmptyPoint(state, startLocation);
-    } else {
-      addPoint(state, startLocation);
-    }
+      return addEmptyPoint(state, startLocation);
+    }
+    return addStopPoint(state, startLocation);
   }
 
   if (isAssignment(node)) {
     // We only want to pause at literal assignments `var a = foo()`
     const value = node.right || node.init;
     if (!isCall(value)) {
-      addPoint(state, startLocation);
+      return addStopPoint(state, startLocation);
     }
   }
 
   if (isCall(node)) {
     let location = startLocation;
 
     // When functions are chained, we want to use the property location
     // e.g `foo().bar()`
     if (t.isMemberExpression(node.callee)) {
       location = node.callee.property.loc.start;
     }
 
     // NOTE: we do not want to land inside an expression e.g. [], {}, call
-    const stepOver = !inExpression(parent.node, grandParent && grandParent.node);
+    const step = !inExpression(parent.node, grandParent && grandParent.node);
 
     // NOTE: we add a point at the beginning of the expression
     // and each of the calls because the engine does not support
     // column-based member expression calls.
-    addPoint(state, startLocation, { breakpoint: true, stepOver });
+    addPoint(state, startLocation, { break: true, step });
     if (location && !(0, _isEqual2.default)(location, startLocation)) {
-      addPoint(state, location, { breakpoint: true, stepOver });
-    }
+      addPoint(state, location, { break: true, step });
+    }
+
+    return;
   }
 
   if (t.isClassProperty(node)) {
-    addBreakPoint(state, startLocation);
+    return addBreakPoint(state, startLocation);
   }
 
   if (t.isFunction(node)) {
     const { line, column } = node.loc.end;
     addBreakPoint(state, startLocation);
-    addPoint(state, { line, column: column - 1 });
+    return addStopPoint(state, { line, column: column - 1 });
   }
 
   if (t.isProgram(node)) {
     const lastStatement = node.body[node.body.length - 1];
     if (lastStatement) {
-      addPoint(state, lastStatement.loc.end);
-    }
-  }
-}
-
-function formatNode(location, types) {
-  return { location, types };
-}
-
-function addPoint(state, location, types = { breakpoint: true, stepOver: true }) {
-  state.push(formatNode(location, types));
+      return addStopPoint(state, lastStatement.loc.end);
+    }
+  }
+
+  if (!hasPoint(state, startLocation) && inStepExpression(parentNode)) {
+    return addEmptyPoint(state, startLocation);
+  }
+}
+
+function hasPoint(state, { line, column }) {
+  return state[line] && state[line][column];
+}
+
+function addPoint(state, { line, column }, types) {
+  if (!state[line]) {
+    state[line] = {};
+  }
+  state[line][column] = types;
+  return state;
+}
+
+function addStopPoint(state, location) {
+  return addPoint(state, location, { break: true, step: true });
 }
 
 function addEmptyPoint(state, location) {
-  addPoint(state, location, { breakpoint: false, stepOver: false });
+  return addPoint(state, location, {});
 }
 
 function addBreakPoint(state, location) {
-  addPoint(state, location, { breakpoint: true, stepOver: false });
+  return addPoint(state, location, { break: true });
 }
 
 /***/ }),
 
 /***/ 3613:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -21390,54 +21397,16 @@ function mapOriginalExpression(expressio
     return expression;
   }
 
   return (0, _generator2.default)(ast).code;
 }
 
 /***/ }),
 
-/***/ 3624:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseIteratee = __webpack_require__(814),
-    baseUniq = __webpack_require__(562);
-
-/**
- * This method is like `_.uniq` except that it accepts `iteratee` which is
- * invoked for each element in `array` to generate the criterion by which
- * uniqueness is computed. The order of result values is determined by the
- * order they occur in the array. The iteratee is invoked with one argument:
- * (value).
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Array
- * @param {Array} array The array to inspect.
- * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
- * @returns {Array} Returns the new duplicate free array.
- * @example
- *
- * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
- * // => [2.1, 1.2]
- *
- * // The `_.property` iteratee shorthand.
- * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
- * // => [{ 'x': 1 }, { 'x': 2 }]
- */
-function uniqBy(array, iteratee) {
-  return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : [];
-}
-
-module.exports = uniqBy;
-
-
-/***/ }),
-
 /***/ 398:
 /***/ (function(module, exports, __webpack_require__) {
 
 /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(8);
 
 /** Detect free variable `exports`. */
 var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
 
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -657,21 +657,22 @@ let SourceActor = ActorClassWithSpec(sou
   unblackbox: function() {
     this.threadActor.sources.unblackBox(this.url);
   },
 
   /**
    * Handler for the "setPausePoints" packet.
    *
    * @param Array pausePoints
-   *        A list of pausePoint objects
+   *        A dictionary of pausePoint objects
    *
-   *        type PausePoint = {
-   *          location: { line: number, column: number }
-   *          types: { breakpoint: boolean, stepOver: boolean }
+   *        type PausePoints = {
+   *          line: {
+   *            column: { break?: boolean, step?: boolean }
+   *          }
    *        }
    */
   setPausePoints: function(pausePoints) {
     this.pausePoints = pausePoints;
   },
 
   /**
    * Handle a request to set a breakpoint.
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -516,37 +516,43 @@ const ThreadActor = ActorClassWithSpec(t
       }
 
       // Cases 1.1, 1.2
       if (this !== startFrame || startLocation.originalUrl !== newLocation.originalUrl) {
         return pauseAndRespond(this);
       }
 
       const pausePoints = newLocation.originalSourceActor.pausePoints;
+      const lineChanged = startLocation.originalLine !== newLocation.originalLine;
+      const columnChanged = startLocation.originalColumn !== newLocation.originalColumn;
 
       if (!pausePoints) {
         // Case 1.4
-        if (startLocation.originalLine !== newLocation.originalLine) {
+        if (lineChanged) {
           return pauseAndRespond(this);
         }
+
         return undefined;
       }
 
       // Case 1.3
-      if (
-        startLocation.originalLine === newLocation.originalLine
-        && startLocation.originalColumn === newLocation.originalColumn
-      ) {
+      if (!lineChanged && !columnChanged) {
         return undefined;
       }
 
       // When pause points are specified for the source,
       // we should pause when we are at a stepOver pause point
       const pausePoint = findPausePointForLocation(pausePoints, newLocation);
-      if (pausePoint && pausePoint.types.stepOver) {
+      if (pausePoint) {
+        if (pausePoint.step) {
+          return pauseAndRespond(this);
+        }
+      } else if (lineChanged) {
+        // NOTE: if we do not find a pause point we want to
+        // fall back on the old behavior (1.3)
         return pauseAndRespond(this);
       }
 
       // Otherwise, let execution continue (we haven't executed enough code to
       // consider this a "step" yet).
       return undefined;
     };
   },
@@ -1923,20 +1929,18 @@ function findEntryPointsForLine(scripts,
     if (offsets.length) {
       entryPoints.push({ script, offsets });
     }
   }
   return entryPoints;
 }
 
 function findPausePointForLocation(pausePoints, location) {
-  return pausePoints.find(pausePoint =>
-    pausePoint.location.line === location.originalLine
-    && pausePoint.location.column === location.originalColumn
-  );
+  const { originalLine: line, originalColumn: column } = location;
+  return pausePoints[line] && pausePoints[line][column];
 }
 
 /**
  * Unwrap a global that is wrapped in a |Debugger.Object|, or if the global has
  * become a dead object, return |undefined|.
  *
  * @param Debugger.Object wrappedGlobal
  *        The |Debugger.Object| which wraps a global.
--- a/devtools/server/tests/unit/test_stepping-with-pause-points.js
+++ b/devtools/server/tests/unit/test_stepping-with-pause-points.js
@@ -57,22 +57,32 @@ async function test_simple_stepping() {
   equal(step1.type, "paused");
   equal(step1.why.type, "resumeLimit");
   equal(step1.frame.where.line, 3);
   equal(step1.frame.where.column, 8);
 
   equal(gDebuggee.a, undefined);
   equal(gDebuggee.b, undefined);
 
+  dumpn("Step Over to line 4");
+  const step2 = await stepOver(gClient, threadClient);
+  equal(step2.type, "paused");
+  equal(step2.why.type, "resumeLimit");
+  equal(step2.frame.where.line, 4);
+  equal(step2.frame.where.column, 8);
+
+  equal(gDebuggee.a, 1);
+  equal(gDebuggee.b, undefined);
+
   dumpn("Step Over to the end of line 4");
-  const step4 = await stepOver(gClient, threadClient);
-  equal(step4.type, "paused");
-  equal(step4.why.type, "resumeLimit");
-  equal(step4.frame.where.line, 4);
-  equal(step4.frame.where.column, 14);
+  const step3 = await stepOver(gClient, threadClient);
+  equal(step3.type, "paused");
+  equal(step3.why.type, "resumeLimit");
+  equal(step3.frame.where.line, 4);
+  equal(step3.frame.where.column, 14);
   equal(gDebuggee.a, 1);
   equal(gDebuggee.b, 2);
 
   finishClient(gClient, gCallback);
 }
 
 function evaluateTestCode() {
   /* eslint-disable */
@@ -82,9 +92,9 @@ function evaluateTestCode() {
     var a = 1;                          // 3
     var b = 2;`,                        // 4
     gDebuggee,
     "1.8",
     "test_stepping-01-test-code.js",
     1
   );
   /* eslint-disable */
-}
\ No newline at end of file
+}
--- a/dom/webidl/PopupBoxObject.webidl
+++ b/dom/webidl/PopupBoxObject.webidl
@@ -25,46 +25,16 @@ interface PopupBoxObject : BoxObject
   void hidePopup(optional boolean cancel = false);
 
   /**
    * Allow the popup to automatically position itself.
    */
   attribute boolean autoPosition;
 
   /**
-   * If keyboard navigation is enabled, the keyboard may be used to navigate
-   * the menuitems on the popup. Enabling keyboard navigation is the default
-   * behaviour and will install capturing key event listeners on the popup
-   * that do not propagate key events to the contents. If you wish to place
-   * elements in a popup which accept key events, such as textboxes, keyboard
-   * navigation should be disabled.
-   *
-   * Setting ignorekeys="true" on the popup element also disables keyboard
-   * navigation, and is recommended over calling this method.
-   */
-  void enableKeyboardNavigator(boolean enableKeyboardNavigator);
-
-  /**
-   * Enable automatic popup dismissal. This only has effect when called
-   * on an open popup.
-   */
-  void enableRollup(boolean enableRollup);
-
-  /**
-   * Control whether the event that caused the popup to be automatically
-   * dismissed ("rolled up") should be consumed, or dispatched as a
-   * normal event.  This should be set immediately before calling showPopup()
-   * if non-default behavior is desired.
-   */
-  const unsigned long ROLLUP_DEFAULT = 0;   /* widget/platform default */
-  const unsigned long ROLLUP_CONSUME = 1;   /* consume the rollup event */
-  const unsigned long ROLLUP_NO_CONSUME = 2; /* don't consume the rollup event */
-  void setConsumeRollupEvent(unsigned long consume);
-
-  /**
    * Size the popup to the given dimensions
    */
   void sizeTo(long width, long height);
 
   /**
    * Move the popup to a point on screen in CSS pixels.
    */
   void moveTo(long left, long top);
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -144,16 +144,30 @@ class ProfileEntry
 
     // Bits 0...1 hold the Kind. Bits 2...3 are unused. Bits 4...12 hold the
     // Category.
     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> kindAndCategory_;
 
     static int32_t pcToOffset(JSScript* aScript, jsbytecode* aPc);
 
   public:
+    ProfileEntry() = default;
+    ProfileEntry& operator=(const ProfileEntry& other)
+    {
+        label_ = other.label();
+        dynamicString_ = other.dynamicString();
+        void* spScript = other.spOrScript;
+        spOrScript = spScript;
+        int32_t offset = other.lineOrPcOffset;
+        lineOrPcOffset = offset;
+        uint32_t kindAndCategory = other.kindAndCategory_;
+        kindAndCategory_ = kindAndCategory;
+        return *this;
+    }
+
     enum class Kind : uint32_t {
         // A normal C++ frame.
         CPP_NORMAL = 0,
 
         // A special C++ frame indicating the start of a run of JS pseudostack
         // entries. CPP_MARKER_FOR_JS frames are ignored, except for the sp
         // field.
         CPP_MARKER_FOR_JS = 1,
@@ -306,85 +320,93 @@ RegisterContextProfilingEventMarker(JSCo
 //
 class PseudoStack final
 {
   public:
     PseudoStack()
       : stackPointer(0)
     {}
 
-    ~PseudoStack() {
-        // The label macros keep a reference to the PseudoStack to avoid a TLS
-        // access. If these are somehow not all cleared we will get a
-        // use-after-free so better to crash now.
-        MOZ_RELEASE_ASSERT(stackPointer == 0);
-    }
+    ~PseudoStack();
 
     void pushCppFrame(const char* label, const char* dynamicString, void* sp, uint32_t line,
                       js::ProfileEntry::Kind kind, js::ProfileEntry::Category category) {
-        if (stackPointer < MaxEntries) {
-            entries[stackPointer].initCppFrame(label, dynamicString, sp, line, kind, category);
-        }
+        uint32_t oldStackPointer = stackPointer;
+
+        if (MOZ_LIKELY(entryCapacity > oldStackPointer) || MOZ_LIKELY(ensureCapacitySlow()))
+            entries[oldStackPointer].initCppFrame(label, dynamicString, sp, line, kind, category);
 
         // This must happen at the end! The compiler will not reorder this
         // update because stackPointer is Atomic<..., ReleaseAcquire>, so any
         // the writes above will not be reordered below the stackPointer store.
         // Do the read and the write as two separate statements, in order to
         // make it clear that we don't need an atomic increment, which would be
         // more expensive on x86 than the separate operations done here.
         // This thread is the only one that ever changes the value of
         // stackPointer.
-        uint32_t oldStackPointer = stackPointer;
         stackPointer = oldStackPointer + 1;
     }
 
     void pushJsFrame(const char* label, const char* dynamicString, JSScript* script,
                      jsbytecode* pc) {
-        if (stackPointer < MaxEntries) {
-            entries[stackPointer].initJsFrame(label, dynamicString, script, pc);
-        }
+        uint32_t oldStackPointer = stackPointer;
+
+        if (MOZ_LIKELY(entryCapacity > oldStackPointer) || MOZ_LIKELY(ensureCapacitySlow()))
+            entries[oldStackPointer].initJsFrame(label, dynamicString, script, pc);
 
         // This must happen at the end! The compiler will not reorder this
         // update because stackPointer is Atomic<..., ReleaseAcquire>, which
         // makes this assignment a release-store, so the writes above will not
         // be reordered to occur after the stackPointer store.
         // Do the read and the write as two separate statements, in order to
         // make it clear that we don't need an atomic increment, which would be
         // more expensive on x86 than the separate operations done here.
         // This thread is the only one that ever changes the value of
         // stackPointer.
-        uint32_t oldStackPointer = stackPointer;
         stackPointer = oldStackPointer + 1;
     }
 
     void pop() {
         MOZ_ASSERT(stackPointer > 0);
         // Do the read and the write as two separate statements, in order to
         // make it clear that we don't need an atomic decrement, which would be
         // more expensive on x86 than the separate operations done here.
         // This thread is the only one that ever changes the value of
         // stackPointer.
         uint32_t oldStackPointer = stackPointer;
         stackPointer = oldStackPointer - 1;
     }
 
-    uint32_t stackSize() const { return std::min(uint32_t(stackPointer), uint32_t(MaxEntries)); }
+    uint32_t stackSize() const { return std::min(uint32_t(stackPointer), stackCapacity()); }
+    uint32_t stackCapacity() const { return entryCapacity; }
 
   private:
+    // Out of line path for expanding the buffer, since otherwise this would get inlined in every
+    // DOM WebIDL call.
+    MOZ_COLD MOZ_MUST_USE bool ensureCapacitySlow();
+
     // No copying.
     PseudoStack(const PseudoStack&) = delete;
     void operator=(const PseudoStack&) = delete;
 
+    // No moving either.
+    PseudoStack(PseudoStack&&) = delete;
+    void operator=(PseudoStack&&) = delete;
+
+    uint32_t entryCapacity = 0;
+
   public:
-    static const uint32_t MaxEntries = 1024;
 
-    // The stack entries.
-    js::ProfileEntry entries[MaxEntries];
+    // The pointer to the stack entries, this is read from the profiler thread and written from the
+    // current thread.
+    //
+    // This is effectively a unique pointer.
+    mozilla::Atomic<js::ProfileEntry*> entries { nullptr };
 
-    // This may exceed MaxEntries, so instead use the stackSize() method to
+    // This may exceed the entry capacity, so instead use the stackSize() method to
     // determine the number of valid samples in entries. When this is less
     // than MaxEntries, it refers to the first free entry past the top of the
     // in-use stack (i.e. entries[stackPointer - 1] is the top stack entry).
     //
     // WARNING WARNING WARNING
     //
     // This is an atomic variable that uses ReleaseAcquire memory ordering.
     // See the "Concurrency considerations" paragraph at the top of this file
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1211,28 +1211,30 @@ GlobalObject::initModuleProto(JSContext*
 
 ModuleBuilder::ModuleBuilder(JSContext* cx, HandleModuleObject module,
                              const frontend::TokenStreamAnyChars& tokenStream)
   : cx_(cx),
     module_(cx, module),
     tokenStream_(tokenStream),
     requestedModuleSpecifiers_(cx, AtomSet(cx)),
     requestedModules_(cx, RequestedModuleVector(cx)),
-    importedBoundNames_(cx, AtomVector(cx)),
-    importEntries_(cx, ImportEntryVector(cx)),
+    importEntries_(cx, ImportEntryMap(cx)),
     exportEntries_(cx, ExportEntryVector(cx)),
+    exportNames_(cx, AtomSet(cx)),
     localExportEntries_(cx, ExportEntryVector(cx)),
     indirectExportEntries_(cx, ExportEntryVector(cx)),
     starExportEntries_(cx, ExportEntryVector(cx))
 {}
 
 bool
 ModuleBuilder::init()
 {
-    return requestedModuleSpecifiers_.init();
+    return requestedModuleSpecifiers_.init() &&
+           importEntries_.init() &&
+           exportNames_.init();
 }
 
 bool
 ModuleBuilder::buildTables()
 {
     for (const auto& e : exportEntries_) {
         RootedExportEntryObject exp(cx_, e);
         if (!exp->moduleRequest()) {
@@ -1319,33 +1321,37 @@ ModuleBuilder::processImport(frontend::P
     for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
         MOZ_ASSERT(spec->isKind(ParseNodeKind::ImportSpec));
         MOZ_ASSERT(spec->pn_left->isArity(PN_NAME));
         MOZ_ASSERT(spec->pn_right->isArity(PN_NAME));
 
         RootedAtom importName(cx_, spec->pn_left->pn_atom);
         RootedAtom localName(cx_, spec->pn_right->pn_atom);
 
-        if (!importedBoundNames_.append(localName))
-            return false;
-
         uint32_t line;
         uint32_t column;
         tokenStream_.lineAndColumnAt(spec->pn_left->pn_pos.begin, &line, &column);
 
         RootedImportEntryObject importEntry(cx_);
         importEntry = ImportEntryObject::create(cx_, module, importName, localName, line, column);
-        if (!importEntry || !importEntries_.append(importEntry))
+        if (!importEntry || !appendImportEntryObject(importEntry))
             return false;
     }
 
     return true;
 }
 
 bool
+ModuleBuilder::appendImportEntryObject(HandleImportEntryObject importEntry)
+{
+    MOZ_ASSERT(importEntry->localName());
+    return importEntries_.put(importEntry->localName(), importEntry);
+}
+
+bool
 ModuleBuilder::processExport(frontend::ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Export) || pn->isKind(ParseNodeKind::ExportDefault));
     MOZ_ASSERT(pn->getArity() == (pn->isKind(ParseNodeKind::Export) ? PN_UNARY : PN_BINARY));
 
     bool isDefault = pn->getKind() == ParseNodeKind::ExportDefault;
     ParseNode* kid = isDefault ? pn->pn_left : pn->pn_kid;
 
@@ -1512,59 +1518,67 @@ ModuleBuilder::processExportFrom(fronten
     }
 
     return true;
 }
 
 ImportEntryObject*
 ModuleBuilder::importEntryFor(JSAtom* localName) const
 {
-    for (auto import : importEntries_) {
-        if (import->localName() == localName)
-            return import;
-    }
-    return nullptr;
+    MOZ_ASSERT(localName);
+    auto ptr = importEntries_.lookup(localName);
+    if (!ptr)
+        return nullptr;
+
+    return ptr->value();
 }
 
 bool
 ModuleBuilder::hasExportedName(JSAtom* name) const
 {
-    for (auto entry : exportEntries_) {
-        if (entry->exportName() == name)
-            return true;
-    }
-    return false;
+    MOZ_ASSERT(name);
+    return exportNames_.has(name);
 }
 
 bool
 ModuleBuilder::appendExportEntry(HandleAtom exportName, HandleAtom localName, ParseNode* node)
 {
     uint32_t line = 0;
     uint32_t column = 0;
     if (node)
         tokenStream_.lineAndColumnAt(node->pn_pos.begin, &line, &column);
 
     Rooted<ExportEntryObject*> exportEntry(cx_);
     exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr, localName,
                                             line, column);
-    return exportEntry && exportEntries_.append(exportEntry);
+    return exportEntry && appendExportEntryObject(exportEntry);
 }
 
 bool
 ModuleBuilder::appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
                                      HandleAtom importName, ParseNode* node)
 {
     uint32_t line;
     uint32_t column;
     tokenStream_.lineAndColumnAt(node->pn_pos.begin, &line, &column);
 
     Rooted<ExportEntryObject*> exportEntry(cx_);
     exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest, importName, nullptr,
                                             line, column);
-    return exportEntry && exportEntries_.append(exportEntry);
+    return exportEntry && appendExportEntryObject(exportEntry);
+}
+
+bool
+ModuleBuilder::appendExportEntryObject(HandleExportEntryObject exportEntry)
+{
+    if (!exportEntries_.append(exportEntry))
+        return false;
+
+    JSAtom* exportName = exportEntry->exportName();
+    return !exportName || exportNames_.put(exportName);
 }
 
 bool
 ModuleBuilder::maybeAppendRequestedModule(HandleAtom specifier, ParseNode* node)
 {
     if (requestedModuleSpecifiers_.has(specifier))
         return true;
 
@@ -1591,8 +1605,25 @@ ArrayObject* ModuleBuilder::createArray(
         return nullptr;
 
     array->setDenseInitializedLength(length);
     for (uint32_t i = 0; i < length; i++)
         array->initDenseElement(i, ObjectValue(*vector[i]));
 
     return array;
 }
+
+template <typename K, typename V>
+ArrayObject* ModuleBuilder::createArray(const JS::Rooted<GCHashMap<K, V>>& map)
+{
+    uint32_t length = map.count();
+    RootedArrayObject array(cx_, NewDenseFullyAllocatedArray(cx_, length));
+    if (!array)
+        return nullptr;
+
+    array->setDenseInitializedLength(length);
+
+    uint32_t i = 0;
+    for (auto r = map.all(); !r.empty(); r.popFront())
+        array->initDenseElement(i++, ObjectValue(*r.front().value()));
+
+    return array;
+}
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -363,53 +363,56 @@ class MOZ_STACK_CLASS ModuleBuilder
     const ExportEntryVector& localExportEntries() const {
         return localExportEntries_;
     }
 
     bool buildTables();
     bool initModule();
 
   private:
-    using AtomVector = GCVector<JSAtom*>;
-    using ImportEntryVector = GCVector<ImportEntryObject*>;
     using RequestedModuleVector = GCVector<RequestedModuleObject*>;
     using AtomSet = JS::GCHashSet<JSAtom*>;
-    using RootedAtomVector = JS::Rooted<AtomVector>;
-    using RootedImportEntryVector = JS::Rooted<ImportEntryVector>;
+    using ImportEntryMap = GCHashMap<JSAtom*, ImportEntryObject*>;
     using RootedExportEntryVector = JS::Rooted<ExportEntryVector>;
     using RootedRequestedModuleVector = JS::Rooted<RequestedModuleVector>;
     using RootedAtomSet = JS::Rooted<AtomSet>;
+    using RootedImportEntryMap = JS::Rooted<ImportEntryMap>;
 
     JSContext* cx_;
     RootedModuleObject module_;
     const frontend::TokenStreamAnyChars& tokenStream_;
     RootedAtomSet requestedModuleSpecifiers_;
     RootedRequestedModuleVector requestedModules_;
-    RootedAtomVector importedBoundNames_;
-    RootedImportEntryVector importEntries_;
+    RootedImportEntryMap importEntries_;
     RootedExportEntryVector exportEntries_;
+    RootedAtomSet exportNames_;
     RootedExportEntryVector localExportEntries_;
     RootedExportEntryVector indirectExportEntries_;
     RootedExportEntryVector starExportEntries_;
 
     ImportEntryObject* importEntryFor(JSAtom* localName) const;
 
     bool processExportBinding(frontend::ParseNode* pn);
     bool processExportArrayBinding(frontend::ParseNode* pn);
     bool processExportObjectBinding(frontend::ParseNode* pn);
 
+    bool appendImportEntryObject(HandleImportEntryObject importEntry);
+
     bool appendExportEntry(HandleAtom exportName, HandleAtom localName,
                            frontend::ParseNode* node = nullptr);
     bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
                                HandleAtom importName, frontend::ParseNode* node);
+    bool appendExportEntryObject(HandleExportEntryObject exportEntry);
 
     bool maybeAppendRequestedModule(HandleAtom specifier, frontend::ParseNode* node);
 
     template <typename T>
     ArrayObject* createArray(const JS::Rooted<GCVector<T>>& vector);
+    template <typename K, typename V>
+    ArrayObject* createArray(const JS::Rooted<GCHashMap<K, V>>& map);
 };
 
 } // namespace js
 
 template<>
 inline bool
 JSObject::is<js::ModuleNamespaceObject>() const
 {
--- a/js/src/jit-test/tests/modules/import-entries.js
+++ b/js/src/jit-test/tests/modules/import-entries.js
@@ -1,18 +1,34 @@
 // Test importEntries property
 
+function importEntryEq(a, b)
+{
+    return a['moduleRequest'] === b['moduleRequest'] &&
+           a['importName'] === b['importName'] &&
+           a['localName'] === b['localName'];
+}
+
+function findImportEntry(array, target)
+{
+    for (let i = 0; i < array.length; i++) {
+        if (importEntryEq(array[i], target))
+            return i;
+    }
+    return -1;
+}
+
 function testImportEntries(source, expected) {
     var module = parseModule(source);
-    var actual = module.importEntries;
+    var actual = module.importEntries.slice(0);
     assertEq(actual.length, expected.length);
-    for (var i = 0; i < actual.length; i++) {
-        for (var property in expected[i]) {
-            assertEq(actual[i][property], expected[i][property]);
-        }
+    for (var i = 0; i < expected.length; i++) {
+        let index = findImportEntry(actual, expected[i]);
+        assertEq(index >= 0, true);
+        actual.splice(index, 1);
     }
 }
 
 testImportEntries('', []);
 
 testImportEntries('import v from "mod";',
                   [{moduleRequest: 'mod', importName: 'default', localName: 'v'}]);
 
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -435,30 +435,34 @@ UNIFIED_SOURCES += [
 #   template instantiations.
 # jsmath.cpp cannot be built in unified mode because it needs to re-#define the
 #   RtlGenRandom declaration's calling convention in <ntsecapi.h> on Windows.
 # jsutil.cpp cannot be built in unified mode because it is needed for
 #   check-vanilla-allocations.
 # StoreBuffer.cpp cannot be built in unified because its template
 #   instantiations may or may not be needed depending on what it gets bundled
 #   with.
+# perf/ProfilingStack.cpp cannot be built in unified mode because we want to
+#   suppress warnings due to usage of the system allocator, and this allows it
+#   to have a deterministic object name.
 # util/DoubleToString.cpp cannot be built in unified mode because we want to
 #   suppress compiler warnings in third-party dtoa.c.
 # vm/Interpreter.cpp is gigantic and destroys incremental build times for any
 #   files unlucky enough to be unified with it.
 SOURCES += [
     'builtin/Array.cpp',
     'builtin/RegExp.cpp',
     'frontend/Parser.cpp',
     'gc/StoreBuffer.cpp',
     'jsmath.cpp',
     'jsutil.cpp',
     'util/DoubleToString.cpp',
     'vm/Interpreter.cpp',
     'vm/JSAtom.cpp',
+    'vm/ProfilingStack.cpp',
 ]
 
 if CONFIG['JS_POSIX_NSPR']:
     UNIFIED_SOURCES += [
         'vm/PosixNSPR.cpp',
     ]
 
 if CONFIG['MOZ_INSTRUMENTS']:
--- a/js/src/vm/GeckoProfiler-inl.h
+++ b/js/src/vm/GeckoProfiler-inl.h
@@ -16,17 +16,17 @@ namespace js {
 
 inline void
 GeckoProfilerThread::updatePC(JSContext* cx, JSScript* script, jsbytecode* pc)
 {
     if (!cx->runtime()->geckoProfiler().enabled())
         return;
 
     uint32_t sp = pseudoStack_->stackPointer;
-    if (sp - 1 < PseudoStack::MaxEntries) {
+    if (sp - 1 < pseudoStack_->stackCapacity()) {
         MOZ_ASSERT(sp > 0);
         MOZ_ASSERT(pseudoStack_->entries[sp - 1].rawScript() == script);
         pseudoStack_->entries[sp - 1].setPC(pc);
     }
 }
 
 /*
  * This class is used to suppress profiler sampling during
--- a/js/src/vm/GeckoProfiler.cpp
+++ b/js/src/vm/GeckoProfiler.cpp
@@ -210,17 +210,17 @@ GeckoProfilerThread::enter(JSContext* cx
         return false;
     }
 
 #ifdef DEBUG
     // In debug builds, assert the JS pseudo frames already on the stack
     // have a non-null pc. Only look at the top frames to avoid quadratic
     // behavior.
     uint32_t sp = pseudoStack_->stackPointer;
-    if (sp > 0 && sp - 1 < PseudoStack::MaxEntries) {
+    if (sp > 0 && sp - 1 < pseudoStack_->stackCapacity()) {
         size_t start = (sp > 4) ? sp - 4 : 0;
         for (size_t i = start; i < sp - 1; i++)
             MOZ_ASSERT_IF(pseudoStack_->entries[i].isJs(), pseudoStack_->entries[i].pc());
     }
 #endif
 
     pseudoStack_->pushJsFrame("", dynamicString, script, script->code());
     return true;
@@ -229,29 +229,29 @@ GeckoProfilerThread::enter(JSContext* cx
 void
 GeckoProfilerThread::exit(JSScript* script, JSFunction* maybeFun)
 {
     pseudoStack_->pop();
 
 #ifdef DEBUG
     /* Sanity check to make sure push/pop balanced */
     uint32_t sp = pseudoStack_->stackPointer;
-    if (sp < PseudoStack::MaxEntries) {
+    if (sp < pseudoStack_->stackCapacity()) {
         JSRuntime* rt = script->runtimeFromActiveCooperatingThread();
         const char* dynamicString = rt->geckoProfiler().profileString(script, maybeFun);
         /* Can't fail lookup because we should already be in the set */
         MOZ_ASSERT(dynamicString);
 
         // Bug 822041
         if (!pseudoStack_->entries[sp].isJs()) {
             fprintf(stderr, "--- ABOUT TO FAIL ASSERTION ---\n");
             fprintf(stderr, " entries=%p size=%u/%u\n",
                             (void*) pseudoStack_->entries,
                             uint32_t(pseudoStack_->stackPointer),
-                            PseudoStack::MaxEntries);
+                            pseudoStack_->stackCapacity());
             for (int32_t i = sp; i >= 0; i--) {
                 ProfileEntry& entry = pseudoStack_->entries[i];
                 if (entry.isJs())
                     fprintf(stderr, "  [%d] JS %s\n", i, entry.dynamicString());
                 else
                     fprintf(stderr, "  [%d] C line %d %s\n", i, entry.line(), entry.dynamicString());
             }
         }
@@ -377,17 +377,17 @@ GeckoProfilerBaselineOSRMarker::GeckoPro
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     if (!hasProfilerFrame || !cx->runtime()->geckoProfiler().enabled()) {
         profiler = nullptr;
         return;
     }
 
     uint32_t sp = profiler->pseudoStack_->stackPointer;
-    if (sp >= PseudoStack::MaxEntries) {
+    if (sp >= profiler->pseudoStack_->stackCapacity()) {
         profiler = nullptr;
         return;
     }
 
     spBefore_ = sp;
     if (sp == 0)
         return;
 
new file mode 100644
--- /dev/null
+++ b/js/src/vm/ProfilingStack.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "js/ProfilingStack.h"
+
+#include "mozilla/IntegerRange.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/UniquePtrExtensions.h"
+
+#include <algorithm>
+
+using namespace js;
+
+PseudoStack::~PseudoStack()
+{
+    // The label macros keep a reference to the PseudoStack to avoid a TLS
+    // access. If these are somehow not all cleared we will get a
+    // use-after-free so better to crash now.
+    MOZ_RELEASE_ASSERT(stackPointer == 0);
+
+    delete[] entries;
+}
+
+bool
+PseudoStack::ensureCapacitySlow()
+{
+    MOZ_ASSERT(stackPointer >= entryCapacity);
+    const uint32_t kInitialCapacity = 128;
+
+    uint32_t sp = stackPointer;
+    auto newCapacity = std::max(sp + 1,  entryCapacity ? entryCapacity * 2 : kInitialCapacity);
+
+    auto* newEntries =
+        new (mozilla::fallible) js::ProfileEntry[newCapacity];
+    if (MOZ_UNLIKELY(!newEntries))
+        return false;
+
+    // It's important that `entries` / `entryCapacity` / `stackPointer` remain consistent here at
+    // all times.
+    for (auto i : mozilla::IntegerRange(entryCapacity))
+        newEntries[i] = entries[i];
+
+    js::ProfileEntry* oldEntries = entries;
+    entries = newEntries;
+    entryCapacity = newCapacity;
+    delete[] oldEntries;
+
+    return true;
+}
deleted file mode 100644
--- a/layout/base/crashtests/372576.xul
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<window id="yourwindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<script type="text/javascript">
-<![CDATA[
-// put some js code here
-]]>
-</script>
-<toolbox>
-		<toolbar>
-			<toolbarbutton type="menu" class="toolbarbutton-1 firefly_files" label="Crash" tooltiptext="Crash">
-				<menupopup onpopupshown="this.enableKeyboardNavigator(false);">
-					<menuitem>
-						<textbox type="autocomplete" oninput="doFilter(this.value,false)" onchange="doFilter(this.value,false)" />
-					</menuitem>
-				</menupopup>
-			</toolbarbutton>
-		</toolbar>
-	</toolbox>
-</window>
\ No newline at end of file
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -139,17 +139,16 @@ load 367498-2.html
 load 369176-1.html
 load 369547-1.html
 load 369547-2.html
 load 369945-1.xhtml
 load 371681-1.xhtml
 load 372237-1.html
 load 372475-1.xhtml
 load 372550-1.html
-load 372576.xul
 load 373628-1.html
 load 373919.xhtml
 load 374193-1.xhtml
 load 374297-1.html
 load 374297-2.html
 load 376223-1.xhtml
 load 378325-1.html
 load 378682.html
--- a/layout/xul/PopupBoxObject.cpp
+++ b/layout/xul/PopupBoxObject.cpp
@@ -182,46 +182,16 @@ PopupBoxObject::SetAutoPosition(bool aSh
 {
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
     menuPopupFrame->SetAutoPosition(aShouldAutoPosition);
   }
 }
 
 void
-PopupBoxObject::EnableRollup(bool aShouldRollup)
-{
-  // this does nothing now
-}
-
-void
-PopupBoxObject::SetConsumeRollupEvent(uint32_t aConsume)
-{
-  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
-  if (menuPopupFrame) {
-    menuPopupFrame->SetConsumeRollupEvent(aConsume);
-  }
-}
-
-void
-PopupBoxObject::EnableKeyboardNavigator(bool aEnableKeyboardNavigator)
-{
-  if (!mContent)
-    return;
-
-  // Use ignorekeys="true" on the popup instead of using this function.
-  if (aEnableKeyboardNavigator)
-    mContent->AsElement()->UnsetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys,
-                                     true);
-  else
-    mContent->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys,
-                                   NS_LITERAL_STRING("true"), true);
-}
-
-void
 PopupBoxObject::GetPopupState(nsString& aState)
 {
   // set this here in case there's no frame for the popup
   aState.AssignLiteral("closed");
 
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
     switch (menuPopupFrame->PopupState()) {
--- a/layout/xul/PopupBoxObject.h
+++ b/layout/xul/PopupBoxObject.h
@@ -24,21 +24,16 @@ class DOMRect;
 class Element;
 class Event;
 
 class PopupBoxObject final : public BoxObject
 {
 public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(PopupBoxObject, BoxObject)
 
-  // also in PopupBoxObject.webidl
-  static const uint32_t ROLLUP_DEFAULT = 0;   /* widget/platform default */
-  static const uint32_t ROLLUP_CONSUME = 1;   /* consume the rollup event */
-  static const uint32_t ROLLUP_NO_CONSUME = 2; /* don't consume the rollup event */
-
   PopupBoxObject();
 
   nsIContent* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   void ShowPopup(Element* aAnchorElement,
                  Element& aPopupElement,
                  int32_t aXPos,
@@ -48,22 +43,16 @@ public:
                  const nsAString& aPopupAlignment);
 
   void HidePopup(bool aCancel);
 
   bool AutoPosition();
 
   void SetAutoPosition(bool aShouldAutoPosition);
 
-  void EnableKeyboardNavigator(bool aEnableKeyboardNavigator);
-
-  void EnableRollup(bool aShouldRollup);
-
-  void SetConsumeRollupEvent(uint32_t aConsume);
-
   void SizeTo(int32_t aWidth, int32_t aHeight);
 
   void MoveTo(int32_t aLeft, int32_t aTop);
 
   void OpenPopup(Element* aAnchorElement,
                  const nsAString& aPosition,
                  int32_t aXPos,
                  int32_t aYPos,
--- a/layout/xul/crashtests/434458-1.xul
+++ b/layout/xul/crashtests/434458-1.xul
@@ -1,16 +1,15 @@
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="setTimeout(boom, 30);" class="reftest-wait">
 
 <script>
 function boom() {
   var a = document.getElementById('a');
   var x = a.popupBoxObject;
   a.parentNode.removeChild(a);
-  x.enableKeyboardNavigator(true);
   x.openPopup(null, "after_start", 0, 0, false, false, null);
   x.openPopupAtScreen(2, 2, false, null);
   x.showPopup(document.documentElement, a, -1, -1, "popup", "topleft", "topleft");
   x.hidePopup();
   document.documentElement.removeAttribute("class");
 }
 
 </script>
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -51,21 +51,19 @@
 #include "mozilla/EventStates.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/KeyboardEvent.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
-#include "mozilla/dom/PopupBoxObject.h"
 #include <algorithm>
 
 using namespace mozilla;
-using mozilla::dom::PopupBoxObject;
 using mozilla::dom::KeyboardEvent;
 
 int8_t nsMenuPopupFrame::sDefaultLevelIsTop = -1;
 
 DOMTimeStamp nsMenuPopupFrame::sLastKeyTime = 0;
 
 // XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose:
 //  nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml
@@ -104,17 +102,16 @@ nsMenuPopupFrame::nsMenuPopupFrame(Compu
   , mYPos(0)
   , mAlignmentOffset(0)
   , mLastClientOffset(0, 0)
   , mPopupType(ePopupTypePanel)
   , mPopupState(ePopupClosed)
   , mPopupAlignment(POPUPALIGNMENT_NONE)
   , mPopupAnchor(POPUPALIGNMENT_NONE)
   , mPosition(POPUPPOSITION_UNKNOWN)
-  , mConsumeRollupEvent(PopupBoxObject::ROLLUP_DEFAULT)
   , mFlip(FlipType_Default)
   , mIsOpenChanged(false)
   , mIsContextMenu(false)
   , mAdjustOffsetForContextMenu(false)
   , mGeneratedChildren(false)
   , mMenuCanOverlapOSBar(false)
   , mShouldAutoPosition(true)
   , mInContentShell(true)
@@ -1807,22 +1804,16 @@ void nsMenuPopupFrame::CanAdjustEdges(Si
     if (popupAlign == POPUPALIGNMENT_BOTTOMLEFT || popupAlign == POPUPALIGNMENT_BOTTOMRIGHT) {
       aChange.y = 0;
     }
   }
 }
 
 ConsumeOutsideClicksResult nsMenuPopupFrame::ConsumeOutsideClicks()
 {
-  // If the popup has explicitly set a consume mode, honor that.
-  if (mConsumeRollupEvent != PopupBoxObject::ROLLUP_DEFAULT) {
-    return (mConsumeRollupEvent == PopupBoxObject::ROLLUP_CONSUME) ?
-           ConsumeOutsideClicks_True : ConsumeOutsideClicks_ParentOnly;
-  }
-
   if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
                                          nsGkAtoms::consumeoutsideclicks,
                                          nsGkAtoms::_true, eCaseMatters)) {
     return ConsumeOutsideClicks_True;
   }
   if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
                                          nsGkAtoms::consumeoutsideclicks,
                                          nsGkAtoms::_false, eCaseMatters)) {
@@ -2270,22 +2261,16 @@ nsMenuPopupFrame::GetWidget()
 {
   nsView * view = GetRootViewForPopup(this);
   if (!view)
     return nullptr;
 
   return view->GetWidget();
 }
 
-void
-nsMenuPopupFrame::AttachedDismissalListener()
-{
-  mConsumeRollupEvent = PopupBoxObject::ROLLUP_DEFAULT;
-}
-
 // helpers /////////////////////////////////////////////////////////////
 
 nsresult
 nsMenuPopupFrame::AttributeChanged(int32_t aNameSpaceID,
                                    nsAtom* aAttribute,
                                    int32_t aModType)
 
 {
@@ -2453,22 +2438,16 @@ nsMenuPopupFrame::SetAutoPosition(bool a
 {
   mShouldAutoPosition = aShouldAutoPosition;
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm) {
     pm->UpdateFollowAnchor(this);
   }
 }
 
-void
-nsMenuPopupFrame::SetConsumeRollupEvent(uint32_t aConsumeMode)
-{
-  mConsumeRollupEvent = aConsumeMode;
-}
-
 int8_t
 nsMenuPopupFrame::GetAlignmentPosition() const
 {
   // The code below handles most cases of alignment, anchor and position values. Those that are
   // not handled just return POPUPPOSITION_UNKNOWN.
 
   if (mPosition == POPUPPOSITION_OVERLAP || mPosition == POPUPPOSITION_AFTERPOINTER ||
       mPosition == POPUPPOSITION_SELECTION)
--- a/layout/xul/nsMenuPopupFrame.h
+++ b/layout/xul/nsMenuPopupFrame.h
@@ -214,19 +214,16 @@ public:
 
   virtual bool MenuClosed() override { return true; }
 
   virtual void LockMenuUntilClosed(bool aLock) override;
   virtual bool IsMenuLocked() override { return mIsMenuLocked; }
 
   nsIWidget* GetWidget();
 
-  // The dismissal listener gets created and attached to the window.
-  void AttachedDismissalListener();
-
   // Overridden methods
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
                                     nsAtom* aAttribute,
                                     int32_t aModType) override;
@@ -372,17 +369,16 @@ public:
 
   void MoveToAnchor(nsIContent* aAnchorContent,
                     const nsAString& aPosition,
                     int32_t aXPos, int32_t aYPos,
                     bool aAttributesOverride);
 
   bool GetAutoPosition();
   void SetAutoPosition(bool aShouldAutoPosition);
-  void SetConsumeRollupEvent(uint32_t aConsumeMode);
 
   nsIScrollableFrame* GetScrollFrame(nsIFrame* aStart);
 
   void SetOverrideConstraintRect(mozilla::LayoutDeviceIntRect aRect) {
     mOverrideConstraintRect = ToAppUnits(aRect, PresContext()->AppUnitsPerCSSPixel());
   }
 
   // For a popup that should appear anchored at the given rect, determine
@@ -605,18 +601,16 @@ protected:
   nsPopupType mPopupType; // type of popup
   nsPopupState mPopupState; // open state of the popup
 
   // popup alignment relative to the anchor node
   int8_t mPopupAlignment;
   int8_t mPopupAnchor;
   int8_t mPosition;
 
-  // One of PopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
-  uint8_t mConsumeRollupEvent;
   FlipType mFlip; // Whether to flip
 
   struct ReflowCallbackData {
     ReflowCallbackData() :
       mPosted(false),
       mAnchor(nullptr),
       mSizedToPopup(false)
     {}
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -1920,17 +1920,16 @@ nsXULPopupManager::SetCaptureState(nsICo
     mWidget = nullptr;
   }
 
   if (item) {
     nsMenuPopupFrame* popup = item->Frame();
     mWidget = popup->GetWidget();
     if (mWidget) {
       mWidget->CaptureRollupEvents(nullptr, true);
-      popup->AttachedDismissalListener();
     }
   }
 
   UpdateKeyboardListeners();
 }
 
 void
 nsXULPopupManager::UpdateKeyboardListeners()
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was f34f392de5158feb46202e8ae58528bfb42f2759 (2018-03-27 17:45:10 -0400)
+The git commit ID used was 7f4f3b6eaedffb9ac8a0d3199433b0390e82a815 (2018-04-13 23:32:06 +1200)
--- a/media/libcubeb/src/cubeb_audiounit.cpp
+++ b/media/libcubeb/src/cubeb_audiounit.cpp
@@ -1342,34 +1342,35 @@ audiounit_set_channel_layout(AudioUnit u
 
   if (layout == CUBEB_LAYOUT_UNDEFINED) {
     // We leave everything as-is...
     return CUBEB_OK;
   }
 
 
   OSStatus r;
-  int channels = cubeb_channel_layout_nb_channels(layout);
+  uint32_t nb_channels = cubeb_channel_layout_nb_channels(layout);
 
   // We do not use CoreAudio standard layout for lack of documentation on what
   // the actual channel orders are. So we set a custom layout.
-  size_t size = offsetof(AudioChannelLayout, mChannelDescriptions[channels]);
+  size_t size = offsetof(AudioChannelLayout, mChannelDescriptions[nb_channels]);
   auto au_layout = make_sized_audio_channel_layout(size);
   au_layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
-  au_layout->mNumberChannelDescriptions = channels;
+  au_layout->mNumberChannelDescriptions = nb_channels;
+
+  uint32_t channels = 0;
   cubeb_channel_layout channelMap = layout;
-  int i = 0;
-  while (channelMap != 0) {
-    XASSERT(i < channels);
+  for (uint32_t i = 0; channelMap != 0; ++i) {
+    XASSERT(channels < nb_channels);
     uint32_t channel = (channelMap & 1) << i;
     if (channel != 0) {
-      au_layout->mChannelDescriptions[i].mChannelLabel =
+      au_layout->mChannelDescriptions[channels].mChannelLabel =
         cubeb_channel_to_channel_label(static_cast<cubeb_channel>(channel));
-      au_layout->mChannelDescriptions[i].mChannelFlags = kAudioChannelFlags_AllOff;
-      i += 1;
+      au_layout->mChannelDescriptions[channels].mChannelFlags = kAudioChannelFlags_AllOff;
+      channels++;
     }
     channelMap = channelMap >> 1;
   }
 
   r = AudioUnitSetProperty(unit,
                            kAudioUnitProperty_AudioChannelLayout,
                            kAudioUnitScope_Input,
                            AU_OUT_BUS,
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -989,17 +989,16 @@ void wasapi_destroy(cubeb * context);
 
 HRESULT register_notification_client(cubeb_stream * stm)
 {
   HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                                 NULL, CLSCTX_INPROC_SERVER,
                                 IID_PPV_ARGS(stm->device_enumerator.receive()));
   if (FAILED(hr)) {
     LOG("Could not get device enumerator: %lx", hr);
-    XASSERT(hr != CO_E_NOTINITIALIZED);
     return hr;
   }
 
   stm->notification_client.reset(new wasapi_endpoint_notification_client(stm->reconfigure_event));
 
   hr = stm->device_enumerator->RegisterEndpointNotificationCallback(stm->notification_client.get());
   if (FAILED(hr)) {
     LOG("Could not register endpoint notification callback: %lx", hr);
@@ -1036,17 +1035,16 @@ HRESULT unregister_notification_client(c
 HRESULT get_endpoint(com_ptr<IMMDevice> & device, LPCWSTR devid)
 {
   com_ptr<IMMDeviceEnumerator> enumerator;
   HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                                 NULL, CLSCTX_INPROC_SERVER,
                                 IID_PPV_ARGS(enumerator.receive()));
   if (FAILED(hr)) {
     LOG("Could not get device enumerator: %lx", hr);
-    XASSERT(hr != CO_E_NOTINITIALIZED);
     return hr;
   }
 
   hr = enumerator->GetDevice(devid, device.receive());
   if (FAILED(hr)) {
     LOG("Could not get device: %lx", hr);
     return hr;
   }
@@ -1057,17 +1055,16 @@ HRESULT get_endpoint(com_ptr<IMMDevice> 
 HRESULT get_default_endpoint(com_ptr<IMMDevice> & device, EDataFlow direction)
 {
   com_ptr<IMMDeviceEnumerator> enumerator;
   HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                                 NULL, CLSCTX_INPROC_SERVER,
                                 IID_PPV_ARGS(enumerator.receive()));
   if (FAILED(hr)) {
     LOG("Could not get device enumerator: %lx", hr);
-    XASSERT(hr != CO_E_NOTINITIALIZED);
     return hr;
   }
   hr = enumerator->GetDefaultAudioEndpoint(direction, eConsole, device.receive());
   if (FAILED(hr)) {
     LOG("Could not get default audio endpoint: %lx", hr);
     return hr;
   }
 
@@ -2305,17 +2302,16 @@ wasapi_enumerate_devices(cubeb * context
   HRESULT hr;
   UINT cc, i;
   EDataFlow flow;
 
   hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
                         CLSCTX_INPROC_SERVER, IID_PPV_ARGS(enumerator.receive()));
   if (FAILED(hr)) {
     LOG("Could not get device enumerator: %lx", hr);
-    XASSERT(hr != CO_E_NOTINITIALIZED);
     return CUBEB_ERROR;
   }
 
   if (type == CUBEB_DEVICE_TYPE_OUTPUT) flow = eRender;
   else if (type == CUBEB_DEVICE_TYPE_INPUT) flow = eCapture;
   else if (type & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) flow = eAll;
   else return CUBEB_ERROR;
 
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -397,23 +397,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNo
 nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
 
 #include "nsStreamConverterService.h"
 #include "nsMultiMixedConv.h"
 #include "nsHTTPCompressConv.h"
 #include "mozTXTToHTMLConv.h"
 #include "nsUnknownDecoder.h"
 
-#include "nsTXTToHTMLConv.h"
-namespace mozilla {
-namespace net {
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsTXTToHTMLConv, Init)
-} // namespace net
-} // namespace mozilla
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef BUILD_NETWORK_INFO_SERVICE
 #include "nsNetworkInfoService.h"
 typedef mozilla::net::nsNetworkInfoService nsNetworkInfoService;
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetworkInfoService, Init)
 #endif // BUILD_NETWORK_INFO_SERVICE
 
@@ -432,32 +425,30 @@ nsresult NS_NewStreamConv(nsStreamConver
 #define MULTI_BYTERANGES             "?from=multipart/byteranges&to=*/*"
 #define UNKNOWN_CONTENT              "?from=" UNKNOWN_CONTENT_TYPE "&to=*/*"
 #define GZIP_TO_UNCOMPRESSED         "?from=gzip&to=uncompressed"
 #define XGZIP_TO_UNCOMPRESSED        "?from=x-gzip&to=uncompressed"
 #define BROTLI_TO_UNCOMPRESSED       "?from=br&to=uncompressed"
 #define COMPRESS_TO_UNCOMPRESSED     "?from=compress&to=uncompressed"
 #define XCOMPRESS_TO_UNCOMPRESSED    "?from=x-compress&to=uncompressed"
 #define DEFLATE_TO_UNCOMPRESSED      "?from=deflate&to=uncompressed"
-#define PLAIN_TO_HTML                "?from=text/plain&to=text/html"
 
 static const mozilla::Module::CategoryEntry kNeckoCategories[] = {
     { NS_ISTREAMCONVERTER_KEY, FTP_TO_INDEX, "" },
     { NS_ISTREAMCONVERTER_KEY, INDEX_TO_HTML, "" },
     { NS_ISTREAMCONVERTER_KEY, MULTI_MIXED_X, "" },
     { NS_ISTREAMCONVERTER_KEY, MULTI_MIXED, "" },
     { NS_ISTREAMCONVERTER_KEY, MULTI_BYTERANGES, "" },
     { NS_ISTREAMCONVERTER_KEY, UNKNOWN_CONTENT, "" },
     { NS_ISTREAMCONVERTER_KEY, GZIP_TO_UNCOMPRESSED, "" },
     { NS_ISTREAMCONVERTER_KEY, XGZIP_TO_UNCOMPRESSED, "" },
     { NS_ISTREAMCONVERTER_KEY, BROTLI_TO_UNCOMPRESSED, "" },
     { NS_ISTREAMCONVERTER_KEY, COMPRESS_TO_UNCOMPRESSED, "" },
     { NS_ISTREAMCONVERTER_KEY, XCOMPRESS_TO_UNCOMPRESSED, "" },
     { NS_ISTREAMCONVERTER_KEY, DEFLATE_TO_UNCOMPRESSED, "" },
-    { NS_ISTREAMCONVERTER_KEY, PLAIN_TO_HTML, "" },
     NS_BINARYDETECTOR_CATEGORYENTRY,
     { nullptr }
 };
 
 static nsresult
 CreateNewStreamConvServiceFactory(nsISupports* aOuter, REFNSIID aIID, void **aResult)
 {
     if (!aResult) {
@@ -715,17 +706,16 @@ NS_DEFINE_NAMED_CID(NS_NAMEDPIPESERVICE_
 NS_DEFINE_NAMED_CID(NS_DASHBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_FTPDIRLISTINGCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_NSINDEXEDTOHTMLCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_DIRINDEXPARSER_CID);
 NS_DEFINE_NAMED_CID(NS_MULTIMIXEDCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_UNKNOWNDECODER_CID);
 NS_DEFINE_NAMED_CID(NS_BINARYDETECTOR_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPCOMPRESSCONVERTER_CID);
-NS_DEFINE_NAMED_CID(NS_NSTXTTOHTMLCONVERTER_CID);
 NS_DEFINE_NAMED_CID(MOZITXTTOHTMLCONV_CID);
 NS_DEFINE_NAMED_CID(NS_DIRINDEX_CID);
 NS_DEFINE_NAMED_CID(NS_MIMEHEADERPARAM_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPSPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPBASICAUTH_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPDIGESTAUTH_CID);
@@ -839,17 +829,16 @@ static const mozilla::Module::CIDEntry k
     { &kNS_DASHBOARD_CID, false, nullptr, mozilla::net::DashboardConstructor },
     { &kNS_FTPDIRLISTINGCONVERTER_CID, false, nullptr, CreateNewFTPDirListingConv },
     { &kNS_NSINDEXEDTOHTMLCONVERTER_CID, false, nullptr, nsIndexedToHTML::Create },
     { &kNS_DIRINDEXPARSER_CID, false, nullptr, nsDirIndexParserConstructor },
     { &kNS_MULTIMIXEDCONVERTER_CID, false, nullptr, CreateNewMultiMixedConvFactory },
     { &kNS_UNKNOWNDECODER_CID, false, nullptr, CreateNewUnknownDecoderFactory },
     { &kNS_BINARYDETECTOR_CID, false, nullptr, CreateNewBinaryDetectorFactory },
     { &kNS_HTTPCOMPRESSCONVERTER_CID, false, nullptr, CreateNewHTTPCompressConvFactory },
-    { &kNS_NSTXTTOHTMLCONVERTER_CID, false, nullptr, mozilla::net::nsTXTToHTMLConvConstructor },
     { &kMOZITXTTOHTMLCONV_CID, false, nullptr, CreateNewTXTToHTMLConvFactory },
     { &kNS_DIRINDEX_CID, false, nullptr, nsDirIndexConstructor },
     { &kNS_MIMEHEADERPARAM_CID, false, nullptr, nsMIMEHeaderParamImplConstructor },
     { &kNS_FILEPROTOCOLHANDLER_CID, false, nullptr, nsFileProtocolHandlerConstructor },
     { &kNS_HTTPPROTOCOLHANDLER_CID, false, nullptr, mozilla::net::nsHttpHandlerConstructor },
     { &kNS_HTTPSPROTOCOLHANDLER_CID, false, nullptr, mozilla::net::nsHttpsHandlerConstructor },
     { &kNS_HTTPBASICAUTH_CID, false, nullptr, mozilla::net::nsHttpBasicAuthConstructor },
     { &kNS_HTTPDIGESTAUTH_CID, false, nullptr, mozilla::net::nsHttpDigestAuthConstructor },
@@ -970,17 +959,16 @@ static const mozilla::Module::ContractID
     { NS_GENERIC_CONTENT_SNIFFER, &kNS_UNKNOWNDECODER_CID },
     { NS_BINARYDETECTOR_CONTRACTID, &kNS_BINARYDETECTOR_CID },
     { NS_ISTREAMCONVERTER_KEY GZIP_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY XGZIP_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY BROTLI_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY COMPRESS_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY XCOMPRESS_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY DEFLATE_TO_UNCOMPRESSED, &kNS_HTTPCOMPRESSCONVERTER_CID },
-    { NS_ISTREAMCONVERTER_KEY PLAIN_TO_HTML, &kNS_NSTXTTOHTMLCONVERTER_CID },
     { MOZ_TXTTOHTMLCONV_CONTRACTID, &kMOZITXTTOHTMLCONV_CID },
     { "@mozilla.org/dirIndex;1", &kNS_DIRINDEX_CID },
     { NS_MIMEHEADERPARAM_CONTRACTID, &kNS_MIMEHEADERPARAM_CID },
     { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "file", &kNS_FILEPROTOCOLHANDLER_CID },
     { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &kNS_HTTPPROTOCOLHANDLER_CID },
     { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "https", &kNS_HTTPSPROTOCOLHANDLER_CID },
     { NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX "basic", &kNS_HTTPBASICAUTH_CID },
     { NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX "digest", &kNS_HTTPDIGESTAUTH_CID },
--- a/netwerk/streamconv/converters/moz.build
+++ b/netwerk/streamconv/converters/moz.build
@@ -13,17 +13,16 @@ XPIDL_MODULE = 'necko_http'
 UNIFIED_SOURCES += [
     'mozTXTToHTMLConv.cpp',
     'nsDirIndex.cpp',
     'nsDirIndexParser.cpp',
     'nsFTPDirListingConv.cpp',
     'nsHTTPCompressConv.cpp',
     'nsIndexedToHTML.cpp',
     'nsMultiMixedConv.cpp',
-    'nsTXTToHTMLConv.cpp',
     'nsUnknownDecoder.cpp',
     'ParseFTPList.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/modules/brotli/dec',
deleted file mode 100644
--- a/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsTXTToHTMLConv.h"
-#include "nsEscape.h"
-#include "nsStringStream.h"
-#include "nsAutoPtr.h"
-#include "nsIChannel.h"
-#include <algorithm>
-
-#include "mozilla/UniquePtrExtensions.h"
-
-#define TOKEN_DELIMITERS u"\t\r\n "
-
-using namespace mozilla;
-
-// nsISupports methods
-NS_IMPL_ISUPPORTS(nsTXTToHTMLConv,
-                  nsIStreamConverter,
-                  nsITXTToHTMLConv,
-                  nsIRequestObserver,
-                  nsIStreamListener)
-
-
-// nsIStreamConverter methods
-NS_IMETHODIMP
-nsTXTToHTMLConv::Convert(nsIInputStream *aFromStream,
-                         const char *aFromType, const char *aToType,
-                         nsISupports *aCtxt, nsIInputStream * *_retval)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsTXTToHTMLConv::AsyncConvertData(const char *aFromType,
-                                  const char *aToType,
-                                  nsIStreamListener *aListener,
-                                  nsISupports *aCtxt)
-{
-    NS_ASSERTION(aListener, "null pointer");
-    mListener = aListener;
-    return NS_OK;
-}
-
-
-// nsIRequestObserver methods
-NS_IMETHODIMP
-nsTXTToHTMLConv::OnStartRequest(nsIRequest* request, nsISupports *aContext)
-{
-    mBuffer.AssignLiteral("<html>\n<head><title>");
-    mBuffer.Append(mPageTitle);
-    mBuffer.AppendLiteral("</title></head>\n<body>\n");
-    if (mPreFormatHTML) {     // Use <pre> tags
-        mBuffer.AppendLiteral("<pre>\n");
-    }
-
-    // Push mBuffer to the listener now, so the initial HTML will not
-    // be parsed in OnDataAvailable().
-
-    nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
-    if (channel)
-        channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
-    // else, assume there is a channel somewhere that knows what it is doing!
-
-    nsresult rv = mListener->OnStartRequest(request, aContext);
-    if (NS_FAILED(rv)) return rv;
-
-    // The request may have been canceled, and if that happens, we want to
-    // suppress calls to OnDataAvailable.
-    request->GetStatus(&rv);
-    if (NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIInputStream> inputData;
-    rv = NS_NewCStringInputStream(getter_AddRefs(inputData),
-                                  NS_LossyConvertUTF16toASCII(mBuffer));
-    if (NS_FAILED(rv)) return rv;
-
-    rv = mListener->OnDataAvailable(request, aContext,
-                                    inputData, 0, mBuffer.Length());
-    if (NS_FAILED(rv)) return rv;
-    mBuffer.Truncate();
-    return rv;
-}
-
-NS_IMETHODIMP
-nsTXTToHTMLConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
-                               nsresult aStatus)
-{
-    nsresult rv = NS_OK;
-    if (mToken) {
-        // we still have an outstanding token
-        NS_ASSERTION(mToken->prepend,
-                     "Non prepending tokens should be handled in "
-                     "OnDataAvailable. There should only be a single "
-                     "prepending token left to be processed.");
-        (void)CatHTML(0, mBuffer.Length());
-    }
-    if (mPreFormatHTML) {
-        mBuffer.AppendLiteral("</pre>\n");
-    }
-    mBuffer.AppendLiteral("\n</body></html>");
-
-    nsCOMPtr<nsIInputStream> inputData;
-    rv = NS_NewCStringInputStream(getter_AddRefs(inputData),
-                                  NS_LossyConvertUTF16toASCII(mBuffer));
-    if (NS_FAILED(rv)) return rv;
-
-    rv = mListener->OnDataAvailable(request, aContext,
-                                    inputData, 0, mBuffer.Length());
-    if (NS_FAILED(rv)) return rv;
-
-    return mListener->OnStopRequest(request, aContext, aStatus);
-}
-
-// nsITXTToHTMLConv methods
-NS_IMETHODIMP
-nsTXTToHTMLConv::SetTitle(const char16_t *aTitle)
-{
-    mPageTitle.Assign(aTitle);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTXTToHTMLConv::PreFormatHTML(bool value)
-{
-    mPreFormatHTML = value;
-    return NS_OK;
-}
-
-// nsIStreamListener method
-NS_IMETHODIMP
-nsTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsISupports *aContext,
-                                 nsIInputStream *aInStream,
-                                 uint64_t aOffset, uint32_t aCount)
-{
-    nsresult rv = NS_OK;
-    nsString pushBuffer;
-    uint32_t amtRead = 0;
-    auto buffer = MakeUniqueFallible<char[]>(aCount+1);
-    if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
-
-    do {
-        uint32_t read = 0;
-        // XXX readSegments, to avoid the first copy?
-        rv = aInStream->Read(buffer.get(), aCount-amtRead, &read);
-        if (NS_FAILED(rv)) return rv;
-
-        buffer[read] = '\0';
-        // XXX charsets?? non-latin1 characters?? utf-16??
-        AppendASCIItoUTF16(buffer.get(), mBuffer);
-        amtRead += read;
-
-        int32_t front = -1, back = -1, tokenLoc = -1, cursor = 0;
-
-        while ( (tokenLoc = FindToken(cursor, &mToken)) > -1) {
-            if (mToken->prepend) {
-                front = mBuffer.RFindCharInSet(TOKEN_DELIMITERS, tokenLoc);
-                front++;
-                back = mBuffer.FindCharInSet(TOKEN_DELIMITERS, tokenLoc);
-            } else {
-                front = tokenLoc;
-                back = front + mToken->token.Length();
-            }
-            if (back == -1) {
-                // didn't find an ending, buffer up.
-                mBuffer.Left(pushBuffer, front);
-                cursor = front;
-                break;
-            }
-            // found the end of the token.
-            cursor = CatHTML(front, back);
-        }
-
-        int32_t end = mBuffer.RFind(TOKEN_DELIMITERS, mBuffer.Length());
-        mBuffer.Left(pushBuffer, std::max(cursor, end));
-        mBuffer.Cut(0, std::max(cursor, end));
-        cursor = 0;
-
-        if (!pushBuffer.IsEmpty()) {
-            nsCOMPtr<nsIInputStream> inputData;
-            rv = NS_NewCStringInputStream(getter_AddRefs(inputData),
-                                          NS_LossyConvertUTF16toASCII(pushBuffer));
-            if (NS_FAILED(rv))
-                return rv;
-
-            rv = mListener->OnDataAvailable(request, aContext,
-                                            inputData, 0, pushBuffer.Length());
-            if (NS_FAILED(rv))
-                return rv;
-        }
-    } while (amtRead < aCount);
-
-    return rv;
-}
-
-// nsTXTToHTMLConv methods
-nsTXTToHTMLConv::nsTXTToHTMLConv()
-{
-    mToken = nullptr;
-    mPreFormatHTML = false;
-}
-
-nsTXTToHTMLConv::~nsTXTToHTMLConv()
-{
-    mTokens.Clear();
-}
-
-nsresult
-nsTXTToHTMLConv::Init()
-{
-    nsresult rv = NS_OK;
-
-    // build up the list of tokens to handle
-    convToken *token = new convToken;
-    if (!token) return NS_ERROR_OUT_OF_MEMORY;
-    token->prepend = false;
-    token->token.Assign(char16_t('<'));
-    token->modText.AssignLiteral("&lt;");
-    mTokens.AppendElement(token);
-
-    token = new convToken;
-    if (!token) return NS_ERROR_OUT_OF_MEMORY;
-    token->prepend = false;
-    token->token.Assign(char16_t('>'));
-    token->modText.AssignLiteral("&gt;");
-    mTokens.AppendElement(token);
-
-    token = new convToken;
-    if (!token) return NS_ERROR_OUT_OF_MEMORY;
-    token->prepend = false;
-    token->token.Assign(char16_t('&'));
-    token->modText.AssignLiteral("&amp;");
-    mTokens.AppendElement(token);
-
-    token = new convToken;
-    if (!token) return NS_ERROR_OUT_OF_MEMORY;
-    token->prepend = true;
-    token->token.AssignLiteral("http://"); // XXX need to iterate through all protos
-    mTokens.AppendElement(token);
-
-    token = new convToken;
-    if (!token) return NS_ERROR_OUT_OF_MEMORY;
-    token->prepend = true;
-    token->token.Assign(char16_t('@'));
-    token->modText.AssignLiteral("mailto:");
-    mTokens.AppendElement(token);
-
-    return rv;
-}
-
-int32_t
-nsTXTToHTMLConv::FindToken(int32_t cursor, convToken* *_retval)
-{
-    int32_t loc = -1, firstToken = mBuffer.Length();
-    int8_t token = -1;
-    for (uint8_t i=0; i < mTokens.Length(); i++) {
-        loc = mBuffer.Find(mTokens[i]->token, cursor);
-        if (loc != -1)
-            if (loc < firstToken) {
-                firstToken = loc;
-                token = i;
-            }
-    }
-    if (token == -1)
-        return -1;
-
-    *_retval = mTokens[token];
-    return firstToken;
-}
-
-int32_t
-nsTXTToHTMLConv::CatHTML(int32_t front, int32_t back)
-{
-    int32_t cursor = 0;
-    int32_t modLen = mToken->modText.Length();
-    if (!mToken->prepend) {
-        // replace the entire token (from delimiter to delimiter)
-        mBuffer.Cut(front, back - front);
-        mBuffer.Insert(mToken->modText, front);
-        cursor = front+modLen;
-    } else {
-        nsString linkText;
-        // href is implied
-        mBuffer.Mid(linkText, front, back-front);
-
-        mBuffer.InsertLiteral(u"<a href=\"", front);
-        cursor += front+9;
-        if (modLen) {
-            mBuffer.Insert(mToken->modText, cursor);
-            cursor += modLen;
-        }
-
-        NS_ConvertUTF16toUTF8 linkTextUTF8(linkText);
-        nsCString escaped;
-        if (NS_EscapeURL(linkTextUTF8.Data(), linkTextUTF8.Length(), esc_Minimal, escaped)) {
-            mBuffer.Cut(cursor, back - front);
-            CopyUTF8toUTF16(escaped, linkText);
-            mBuffer.Insert(linkText, cursor);
-            back = front + linkText.Length();
-        }
-
-        cursor += back-front;
-        mBuffer.InsertLiteral(u"\">", cursor);
-        cursor += 2;
-        mBuffer.Insert(linkText, cursor);
-        cursor += linkText.Length();
-        mBuffer.InsertLiteral(u"</a>", cursor);
-        cursor += 4;
-    }
-    mToken = nullptr; // indicates completeness
-    return cursor;
-}
deleted file mode 100644
--- a/netwerk/streamconv/converters/nsTXTToHTMLConv.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ____nstxttohtmlconv___h___
-#define ____nstxttohtmlconv___h___
-
-#include "nsITXTToHTMLConv.h"
-#include "nsCOMPtr.h"
-#include "nsTArray.h"
-#include "nsString.h"
-
-#define NS_NSTXTTOHTMLCONVERTER_CID                         \
-{ /* 9ef9fa14-1dd1-11b2-9d65-d72d6d1f025e */ \
-    0x9ef9fa14, \
-    0x1dd1, \
-    0x11b2, \
-    {0x9d, 0x65, 0xd7, 0x2d, 0x6d, 0x1f, 0x02, 0x5e} \
-}
-
-// Internal representation of a "token"
-typedef struct convToken {
-    nsString token;     // the actual string (i.e. "http://")
-    nsString modText;   // replacement text or href prepend text.
-    bool     prepend;   // flag indicating how the modText should be used.
-} convToken;
-
-template<class T> class nsAutoPtr;
-
-/**
- * Convert plain text to HTML.
- *
- * OVERVIEW OF HOW THIS CLASS WORKS:
- *
- * This class stores an array of tokens that should be replaced by something,
- * or something that should be prepended.
- * The "token" member of convToken is the text to search for. This is a
- * substring of the desired token. Tokens are delimited by TOKEN_DELIMITERS.
- * That entire token will be replaced by modText (if prepend is false); or it
- * will be linkified and modText will be prepended to the token if prepend is
- * true.
- *
- * Note that all of the text will be in a preformatted block, so there is no
- * need to emit line-end tags, or set the font face to monospace.
- *
- * This works as a stream converter, so data will arrive by
- * OnStartRequest/OnDataAvailable/OnStopRequest calls.
- *
- * OStopR will possibly process a remaining token.
- *
- * If the data of one pass contains a part of a token, that part will be stored
- * in mBuffer. The rest of the data will be sent to the next listener.
- *
- * XXX this seems suboptimal. this means that this design will only work for
- * links. and it is impossible to append anything to the token. this means that,
- * for example, making *foo* bold is not possible.
- */
-class nsTXTToHTMLConv : public nsITXTToHTMLConv {
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSISTREAMCONVERTER
-    NS_DECL_NSITXTTOHTMLCONV
-    NS_DECL_NSIREQUESTOBSERVER
-    NS_DECL_NSISTREAMLISTENER
-
-    nsTXTToHTMLConv();
-    nsresult Init();
-
-protected:
-    virtual ~nsTXTToHTMLConv();
-
-    // return the token and it's location in the underlying buffer.
-    int32_t FindToken(int32_t cursor, convToken* *_retval);
-
-    // return the cursor location after munging HTML into the
-    // underlying buffer, according to mToken
-    int32_t CatHTML(int32_t front, int32_t back);
-
-    nsCOMPtr<nsIStreamListener>     mListener; // final listener (consumer)
-    nsString                        mBuffer;   // any carry over data
-    nsTArray<nsAutoPtr<convToken> > mTokens;   // list of tokens to search for
-    convToken                       *mToken;   // current token (if any)
-    nsString                        mPageTitle; // Page title
-    bool                            mPreFormatHTML; // Whether to use <pre> tags
-};
-
-#endif // ____nstxttohtmlconv___h___
-
--- a/security/sandbox/win/SandboxInitialization.cpp
+++ b/security/sandbox/win/SandboxInitialization.cpp
@@ -101,28 +101,29 @@ InitializeHandleVerifier()
   if (ShouldDisableHandleVerifier() || !EnableHandleCloseMonitoring()) {
     base::win::DisableHandleVerifier();
   }
 }
 
 static sandbox::TargetServices*
 InitializeTargetServices()
 {
+  // This might disable the verifier, so we want to do it before it is used.
+  InitializeHandleVerifier();
+
   sandbox::TargetServices* targetServices =
     sandbox::SandboxFactory::GetTargetServices();
   if (!targetServices) {
     return nullptr;
   }
 
   if (targetServices->Init() != sandbox::SBOX_ALL_OK) {
     return nullptr;
   }
 
-  InitializeHandleVerifier();
-
   return targetServices;
 }
 
 sandbox::TargetServices*
 GetInitializedTargetServices()
 {
   static sandbox::TargetServices* sInitializedTargetServices =
     InitializeTargetServices();
@@ -134,16 +135,19 @@ void
 LowerSandbox()
 {
   GetInitializedTargetServices()->LowerToken();
 }
 
 static sandbox::BrokerServices*
 InitializeBrokerServices()
 {
+  // This might disable the verifier, so we want to do it before it is used.
+  InitializeHandleVerifier();
+
   sandbox::BrokerServices* brokerServices =
     sandbox::SandboxFactory::GetBrokerServices();
   if (!brokerServices) {
     return nullptr;
   }
 
   if (brokerServices->Init() != sandbox::SBOX_ALL_OK) {
     return nullptr;
@@ -153,18 +157,16 @@ InitializeBrokerServices()
   // Precreate the desktop and window station used by the renderers.
   // IMPORTANT: This piece of code needs to run as early as possible in the
   // process because it will initialize the sandbox broker, which requires
   // the process to swap its window station. During this time all the UI
   // will be broken. This has to run before threads and windows are created.
   scoped_refptr<sandbox::TargetPolicy> policy = brokerServices->CreatePolicy();
   sandbox::ResultCode result = policy->CreateAlternateDesktop(true);
 
-  InitializeHandleVerifier();
-
   return brokerServices;
 }
 
 sandbox::BrokerServices*
 GetInitializedBrokerServices()
 {
   static sandbox::BrokerServices* sInitializedBrokerServices =
     InitializeBrokerServices();
--- a/toolkit/components/downloads/DownloadCore.jsm
+++ b/toolkit/components/downloads/DownloadCore.jsm
@@ -406,16 +406,21 @@ this.Download.prototype = {
       // In case the download was restarted while cancellation was in progress,
       // but the previous attempt actually succeeded before cancellation could
       // be processed, it is possible that the download has already finished.
       if (this.succeeded) {
         return;
       }
 
       try {
+        if (this.downloadingToSameFile()) {
+          throw new DownloadError({ message: "Can't overwrite the source file.",
+                                    becauseTargetFailed: true });
+        }
+
         // Disallow download if parental controls service restricts it.
         if (await DownloadIntegration.shouldBlockForParentalControls(this)) {
           throw new DownloadError({ becauseBlockedByParentalControls: true });
         }
 
         // Disallow download if needed runtime permissions have not been granted
         // by user.
         if (await DownloadIntegration.shouldBlockForRuntimePermissions()) {
@@ -824,16 +829,33 @@ this.Download.prototype = {
         }
       })();
     }
 
     return this._promiseRemovePartialData;
   },
 
   /**
+   * Returns true if the download source is the same as the target file.
+   */
+  downloadingToSameFile() {
+    if (!this.source.url || !this.source.url.startsWith("file:")) {
+      return false;
+    }
+
+    try {
+      let sourceUri = NetUtil.newURI(this.source.url);
+      let targetUri = NetUtil.newURI(new FileUtils.File(this.target.path));
+      return sourceUri.equals(targetUri);
+    } catch (ex) {
+      return false;
+    }
+  },
+
+  /**
    * This deferred object contains a promise that is resolved as soon as this
    * download finishes successfully, and is never rejected.  This property is
    * initialized when the download is created, and never changes.
    */
   _deferSucceeded: null,
 
   /**
    * Returns a promise that is resolved as soon as this download finishes
--- a/toolkit/components/downloads/test/unit/test_DownloadCore.js
+++ b/toolkit/components/downloads/test/unit/test_DownloadCore.js
@@ -17,16 +17,34 @@ ChromeUtils.defineModuleGetter(this, "Do
 var gUseLegacySaver = false;
 
 var scriptFile = do_get_file("common_test_Download.js");
 Services.scriptloader.loadSubScript(NetUtil.newURI(scriptFile).spec);
 
 // Tests
 
 /**
+ * The download should fail early if the source and the target are the same.
+ */
+add_task(async function test_error_target_downloadingToSameFile() {
+  let targetFile = getTempFile(TEST_TARGET_FILE_NAME);
+  targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
+
+  let download = await Downloads.createDownload({
+    source: NetUtil.newURI(targetFile),
+    target: targetFile,
+  });
+  await Assert.rejects(download.start(), ex => ex instanceof Downloads.Error &&
+                                               ex.becauseTargetFailed);
+
+  Assert.ok(await OS.File.exists(download.target.path),
+            "The file should not have been deleted.");
+});
+
+/**
  * Tests the DownloadError object.
  */
 add_task(function test_DownloadError() {
   let error = new DownloadError({ result: Cr.NS_ERROR_NOT_RESUMABLE,
                                   message: "Not resumable."});
   Assert.equal(error.result, Cr.NS_ERROR_NOT_RESUMABLE);
   Assert.equal(error.message, "Not resumable.");
   Assert.ok(!error.becauseSourceFailed);
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -154,22 +154,24 @@ browser.engagement:
       - rweiss@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
   restored_pinned_tabs_count:
     bug_numbers:
       - 1373728
+      - 1451475
     description: >
       The count of the number of pinned tabs that were restored.
-    expires: '62'
+    expires: '67'
     kind: uint
     notification_emails:
       - chutten@mozilla.com
+      - jrediger@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
   active_ticks:
     bug_numbers:
       - 1376942
     description: >
--- a/toolkit/content/tests/chrome/test_popup_keys.xul
+++ b/toolkit/content/tests/chrome/test_popup_keys.xul
@@ -43,19 +43,16 @@ function waitForEvent(target, eventName)
     }, false);
   });
 }
 
 function runTests()
 {
   (async function() {
     var popup = $("popup");
-    popup.enableKeyboardNavigator(false);
-    is(popup.getAttribute("ignorekeys"), "true", "keys disabled");
-    popup.enableKeyboardNavigator(true);
     is(popup.hasAttribute("ignorekeys"), false, "keys enabled");
 
     let popupShownPromise = waitForEvent(popup, "popupshown");
     popup.openPopup(null, "after_start");
     await popupShownPromise;
 
     let popupHiddenPromise = waitForEvent(popup, "popuphidden");
     synthesizeKey("KEY_ArrowDown");
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -175,34 +175,16 @@
       <property name="alignmentOffset" readonly="true">
         <getter>
         <![CDATA[
           return this.popupBoxObject.alignmentOffset;
         ]]>
         </getter>
       </property>
 
-      <method name="enableKeyboardNavigator">
-        <parameter name="aEnableKeyboardNavigator"/>
-        <body>
-        <![CDATA[
-          this.popupBoxObject.enableKeyboardNavigator(aEnableKeyboardNavigator);
-        ]]>
-        </body>
-      </method>
-
-      <method name="enableRollup">
-        <parameter name="aEnableRollup"/>
-        <body>
-        <![CDATA[
-          this.popupBoxObject.enableRollup(aEnableRollup);
-        ]]>
-        </body>
-      </method>
-
       <method name="sizeTo">
         <parameter name="aWidth"/>
         <parameter name="aHeight"/>
         <body>
         <![CDATA[
           this.popupBoxObject.sizeTo(aWidth, aHeight);
         ]]>
         </body>
--- a/widget/GfxDriverInfo.cpp
+++ b/widget/GfxDriverInfo.cpp
@@ -301,16 +301,24 @@ const GfxDeviceFamily* GfxDriverInfo::Ge
       break;
     case Bug1116812:
       APPEND_DEVICE(0x2e32);
       APPEND_DEVICE(0x2a02);
       break;
     case Bug1155608:
       APPEND_DEVICE(0x2e22); /* IntelG45_1 */
       break;
+    case Bug1447141:
+      APPEND_DEVICE(0x9991);
+      APPEND_DEVICE(0x9993);
+      APPEND_DEVICE(0x9996);
+      APPEND_DEVICE(0x9998);
+      APPEND_DEVICE(0x9901);
+      APPEND_DEVICE(0x990b);
+      break;
     case Bug1207665:
       APPEND_DEVICE(0xa001); /* Intel Media Accelerator 3150 */
       APPEND_DEVICE(0xa002);
       APPEND_DEVICE(0xa011);
       APPEND_DEVICE(0xa012);
       break;
     // This should never happen, but we get a warning if we don't handle this.
     case DeviceFamilyMax:
--- a/widget/GfxDriverInfo.h
+++ b/widget/GfxDriverInfo.h
@@ -93,16 +93,17 @@ enum DeviceFamily {
   RadeonX1000,
   Geforce7300GT,
   Nvidia310M,
   Nvidia8800GTS,
   Bug1137716,
   Bug1116812,
   Bug1155608,
   Bug1207665,
+  Bug1447141,
   DeviceFamilyMax
 };
 
 enum DeviceVendor {
   VendorAll, // There is an assumption that this is the first enum
   VendorIntel,
   VendorNVIDIA,
   VendorAMD,
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1388,16 +1388,27 @@ GfxInfo::GetGfxDriverInfo()
       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1359416");
 
     // bug 1419264
     APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::Windows7,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
       nsIGfxInfo::FEATURE_ADVANCED_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_BETWEEN_INCLUSIVE, V(23,21,13,8569), V(23,21,13,9135),
       "FEATURE_FAILURE_BUG_1419264", "Windows 10");
+
+    // Bug 1447141, for causing device creation crashes.
+    APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows7,
+      (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1447141),
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
+      DRIVER_EQUAL, V(15, 201, 2201, 0), "FEATURE_FAILURE_BUG_1447141_1");
+    APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows7,
+      (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1447141),
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
+      DRIVER_EQUAL, V(15, 201, 1701, 0), "FEATURE_FAILURE_BUG_1447141_1");
+
   }
   return *mDriverInfo;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
                               int32_t *aStatus,
                               nsAString & aSuggestedDriverVersion,