Merge inbound to mozilla-central. a=merge
authorshindli <shindli@mozilla.com>
Fri, 30 Mar 2018 12:56:21 +0300
changeset 410761 b7fa9d95150ec24e3c8d11106153f76be4507356
parent 410733 3f37287132bff08037b75b07e5485fcaa29ee886 (current diff)
parent 410760 9b4b4e4924b31d2c408c6e65f30775babd31a99f (diff)
child 410762 44aceee694bec3dc6a7757395d25553ae87ab166
child 410767 e29f8477cc6b6ae09c1222f851108607e259bee9
child 410796 4992808ab5a3a4887162815aad2bc0793fe72b9f
push id33736
push usershindli@mozilla.com
push dateFri, 30 Mar 2018 09:56:41 +0000
treeherdermozilla-central@b7fa9d95150e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone61.0a1
first release with
nightly linux32
b7fa9d95150e / 61.0a1 / 20180330100123 / files
nightly linux64
b7fa9d95150e / 61.0a1 / 20180330100123 / files
nightly mac
b7fa9d95150e / 61.0a1 / 20180330100123 / files
nightly win32
b7fa9d95150e / 61.0a1 / 20180330100123 / files
nightly win64
b7fa9d95150e / 61.0a1 / 20180330100123 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
layout/generic/nsFrame.cpp
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -1,14 +1,15 @@
 # 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 $(topsrcdir)/config/rules.mk
 
 # run the binscope tool to make sure the binary and all libraries
 # are using all available Windows OS-level security mechanisms
-# Don't do this in clang-cl since it doesn't support debug information yet.
-ifndef CLANG_CL
+# XXX this should use a better way of checking all our binaries
 check::
 	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/crashreporter-symbols/
 	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/plugin-container.exe $(DIST)/crashreporter-symbols/
-endif
+	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/mozglue.dll $(DIST)/crashreporter-symbols/
+	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/xul.dll $(DIST)/crashreporter-symbols/
+	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/nss3.dll $(DIST)/crashreporter-symbols/
--- a/build/win32/autobinscope.py
+++ b/build/win32/autobinscope.py
@@ -1,22 +1,18 @@
 #!/usr/bin/env python
 
 # 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/.
 
-# run Microsoft's Binscope tool (http://www.microsoft.com/download/en/details.aspx?id=11910)
+# run Microsoft's Binscope tool (https://www.microsoft.com/en-us/download/details.aspx?id=44995)
 # against a fresh Windows build. output a 'binscope.log' file with full details
 # of the run and appropriate strings to integrate with the buildbots
 
-# from the docs : "The error code returned when running under the command line is equal 
-# to the number of failures the tool reported plus the number of errors. BinScope will return 
-# 0 only if there are no errors or failures."
-
 # the symbol dir should point to the symbol dir hierarchy created
 # via running make buildsymbols in a windows build's objdir
 
 import sys
 import subprocess
 import os
 
 BINSCOPE_OUTPUT_LOGFILE = r".\binscope_xml_output.log"
@@ -35,41 +31,67 @@ if len(sys.argv) == 4:
 else:
   log_file_path = BINSCOPE_OUTPUT_LOGFILE
   
 # execute binscope against the binary, using the BINSCOPE environment
 # variable as the path to binscope.exe
 try:
   binscope_path = os.environ['BINSCOPE']
 except KeyError:
-  print "BINSCOPE environment variable is not set, can't check DEP/ASLR etc. status."
+  print "TEST-UNEXPECTED-FAIL | autobinscope.py | BINSCOPE environment variable is not set, can't check DEP/ASLR etc. status."
   sys.exit(0)
   
 try:    
-  proc = subprocess.Popen([binscope_path, "/target", binary_path,
-    "/output", log_file_path, "/sympath", symbol_path,
-    "/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck",
-    "/c", "GSCheck", "/c", "GSFriendlyInitCheck",
-    "/c", "CompilerVersionCheck", "/c", "SafeSEHCheck", "/c", "SNCheck",
-    "/c", "DBCheck"], stdout=subprocess.PIPE)
+  proc = subprocess.Popen([
+    binscope_path,
+    "/NoLogo",
+    "/Target", binary_path,
+    "/SymPath", symbol_path,
+    "/Checks", "ATLVersionCheck",
+    "/Checks", "ATLVulnCheck",
+    # We do not ship in the Windows Store
+    "/SkippedChecks", "AppContainerCheck",
+    # The CompilerVersionCheck doesn't like clang-cl (we would need to set MinimumCompilerVersion)
+    # But we check the compiler in our build system anyway, so this doesn't seem useful
+    "/SkippedChecks", "CompilerVersionCheck",
+    "/Checks", "DBCheck",
+    "/Checks", "DefaultGSCookieCheck",
+    "/Checks", "ExecutableImportsCheck",
+    # FunctonPointersCheck is disabled per bug 1014002
+    "/SkippedChecks", "FunctionPointersCheck",
+    # GSCheck doesn't know how to deal with Rust libs
+    "/SkippedChecks", "GSCheck",
+    "/Checks", "GSFriendlyInitCheck",
+    # We are not safebuffers-clean, bug 1449951
+    "/SkippedChecks", "GSFunctionSafeBuffersCheck",
+    "/Checks", "HighEntropyVACheck",
+    "/Checks", "NXCheck",
+    "/Checks", "RSA32Check",
+    "/Checks", "SafeSEHCheck",
+    "/Checks", "SharedSectionCheck",
+    "/Checks", "VB6Check",
+    "/Checks", "WXCheck"
+    ], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
 except WindowsError, (errno, strerror): 
   if errno != 2 and errno != 3:
-    print "Unexpected error ! \nError " + str(errno) + " : " + strerror + "\nExiting !\n"
+    print "TEST-UNEXPECTED-FAIL | autobinscope.py | Unexpected error %d : %s" (errno, strerror)
     sys.exit(0)
   else:
-    print "Could not locate binscope at location : %s\n" % binscope_path
-    print "Binscope wasn't installed or the BINSCOPE env variable wasn't set correctly, skipping this check and exiting..."
+    print "TEST-UNEXPECTED-FAIL | autobinscope.py | Could not locate binscope at location : %s\n" % binscope_path
     sys.exit(0)
 
 proc.wait()
 
-output = proc.communicate()[0]
+output = proc.communicate()[1].decode('utf-8').splitlines()
 
-# is this a PASS or a FAIL ? 
+errors = 0
+for line in output:
+  print(line)
+  if 'error' in line:
+    errors += 1
+
 if proc.returncode != 0:
-  print "Error count: %d" % proc.returncode
-  print "TEST-UNEXPECTED-FAIL | autobinscope.py | %s is missing a needed Windows protection, such as /GS or ASLR" % binary_path
-  logfile = open(log_file_path, "r")
-  for line in logfile:
-    print(line),
+  print "TEST-UNEXPECTED-FAIL | autobinscope.py | Binscope returned error code %d for file %s" % (proc.returncode, binary_path)
+elif errors != 0:
+  print "TEST-UNEXPECTED-FAIL | autobinscope.py | Binscope reported %d error(s) for file %s" % (errors, binary_path)
 else:
   print "TEST-PASS | autobinscope.py | %s succeeded" % binary_path
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -1207,22 +1207,16 @@ nsScriptSecurityManager::doGetObjectPrin
 NS_IMETHODIMP
 nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
                                           const nsIID &aIID,
                                           nsISupports *aObj,
                                           nsIClassInfo *aClassInfo)
 {
 // XXX Special case for Exception ?
 
-    uint32_t flags;
-    if (aClassInfo && NS_SUCCEEDED(aClassInfo->GetFlags(&flags)) &&
-        (flags & nsIClassInfo::DOM_OBJECT)) {
-        return NS_OK;
-    }
-
     // We give remote-XUL whitelisted domains a free pass here. See bug 932906.
     JS::Rooted<JS::Realm*> contextRealm(cx, JS::GetCurrentRealmOrNull(cx));
     MOZ_RELEASE_ASSERT(contextRealm);
     if (!xpc::AllowContentXBLScope(contextRealm)) {
         return NS_OK;
     }
 
     if (nsContentUtils::IsCallerChrome()) {
--- 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 30.0
+Version 31.0
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-29...release-30
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-30...release-31
 
 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
@@ -2888,31 +2888,33 @@ const {
 } = __webpack_require__(1389);
 
 const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1363);
 
 const dispatcher = new WorkerDispatcher();
 
 const getOriginalURLs = dispatcher.task("getOriginalURLs");
 const getGeneratedLocation = dispatcher.task("getGeneratedLocation");
+const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations");
 const getOriginalLocation = dispatcher.task("getOriginalLocation");
 const getLocationScopes = dispatcher.task("getLocationScopes");
 const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
 const applySourceMap = dispatcher.task("applySourceMap");
 const clearSourceMaps = dispatcher.task("clearSourceMaps");
 const hasMappedSource = dispatcher.task("hasMappedSource");
 
 module.exports = {
   originalToGeneratedId,
   generatedToOriginalId,
   isGeneratedId,
   isOriginalId,
   hasMappedSource,
   getOriginalURLs,
   getGeneratedLocation,
+  getAllGeneratedLocations,
   getOriginalLocation,
   getLocationScopes,
   getOriginalSourceText,
   applySourceMap,
   clearSourceMaps,
   startSourceMapWorker: dispatcher.start.bind(dispatcher),
   stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
 };
@@ -3619,17 +3621,17 @@ function setSourceTextProps(state, actio
   return updateSource(state, text);
 }
 
 function updateSource(state, source) {
   if (!source.id) {
     return state;
   }
 
-  const existingSource = state.getIn(["sources", source.id]);
+  const existingSource = state.sources.get(source.id);
 
   if (existingSource) {
     const updatedSource = existingSource.merge(source);
     return state.setIn(["sources", source.id], updatedSource);
   }
 
   return state.setIn(["sources", source.id], new SourceRecordClass(source));
 }
@@ -4896,17 +4898,17 @@ function update(state = initialASTState(
 
 // NOTE: we'd like to have the app state fully typed
 // https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185
 function getSymbols(state, source) {
   if (!source) {
     return null;
   }
 
-  return state.ast.getIn(["symbols", source.id]) || null;
+  return state.ast.symbols.get(source.id) || null;
 }
 
 function hasSymbols(state, source) {
   const symbols = getSymbols(state, source);
 
   if (!symbols) {
     return false;
   }
@@ -4928,21 +4930,21 @@ function isEmptyLineInSource(state, line
   return emptyLines && emptyLines.includes(line);
 }
 
 function getEmptyLines(state, source) {
   if (!source) {
     return null;
   }
 
-  return state.ast.getIn(["emptyLines", source.id]);
+  return state.ast.emptyLines.get(source.id);
 }
 
 function getPausePoints(state, sourceId) {
-  return state.ast.getIn(["pausePoints", sourceId]);
+  return state.ast.pausePoints.get(sourceId);
 }
 
 function hasPausePoints(state, sourceId) {
   const pausePoints = getPausePoints(state, sourceId);
   return !!pausePoints;
 }
 
 function getOutOfScopeLocations(state) {
@@ -4950,17 +4952,17 @@ function getOutOfScopeLocations(state) {
 }
 
 function getPreview(state) {
   return state.ast.get("preview");
 }
 
 const emptySourceMetaData = {};
 function getSourceMetaData(state, sourceId) {
-  return state.ast.getIn(["sourceMetaData", sourceId]) || emptySourceMetaData;
+  return state.ast.sourceMetaData.get(sourceId) || emptySourceMetaData;
 }
 
 function hasSourceMetaData(state, sourceId) {
   return state.ast.hasIn(["sourceMetaData", sourceId]);
 }
 
 function getInScopeLines(state) {
   return state.ast.get("inScopeLines");
@@ -5299,16 +5301,17 @@ function trimUrlQuery(url) {
 
   return url.slice(0, q);
 }
 
 // Map suffix to content type.
 const contentMap = {
   "js": "text/javascript",
   "jsm": "text/javascript",
+  "mjs": "text/javascript",
   "ts": "text/typescript",
   "tsx": "text/typescript-jsx",
   "jsx": "text/jsx",
   "coffee": "text/coffeescript",
   "elm": "text/elm",
   "cljs": "text/x-clojure"
 };
 
@@ -6345,24 +6348,24 @@ function evaluateExpression(expression) 
       console.warn("Expressions should not be empty");
       return;
     }
 
     let input = expression.input;
     const frame = (0, _selectors.getSelectedFrame)(getState());
 
     if (frame) {
-      const { location, generatedLocation } = frame;
+      const { location } = frame;
       const source = (0, _selectors.getSource)(getState(), location.sourceId);
       const sourceId = source.get("id");
 
       const selectedSource = (0, _selectors.getSelectedSource)(getState());
 
       if (selectedSource && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) && !(0, _devtoolsSourceMap.isGeneratedId)(selectedSource.get("id"))) {
-        input = await getMappedExpression({ getState, sourceMaps }, generatedLocation, input);
+        input = await dispatch(getMappedExpression(input));
       }
     }
 
     const frameId = (0, _selectors.getSelectedFrameId)(getState());
 
     return dispatch({
       type: "EVALUATE_EXPRESSION",
       input: expression.input,
@@ -6370,23 +6373,28 @@ function evaluateExpression(expression) 
     });
   };
 }
 
 /**
  * Gets information about original variable names from the source map
  * and replaces all posible generated names.
  */
-async function getMappedExpression({ getState, sourceMaps }, generatedLocation, expression) {
-  const mappings = (0, _selectors.getSelectedScopeMappings)(getState());
-  if (!mappings) {
-    return expression;
-  }
-
-  return await parser.mapOriginalExpression(expression, mappings);
+function getMappedExpression(expression) {
+  return async function ({ dispatch, getState, client, sourceMaps }) {
+    const mappings = (0, _selectors.getSelectedScopeMappings)(getState());
+    if (!mappings) {
+      return expression;
+    }
+
+    return await dispatch({
+      type: "MAP_EXPRESSION_RESULT",
+      [_promise.PROMISE]: parser.mapOriginalExpression(expression, mappings)
+    });
+  };
 }
 
 /***/ }),
 
 /***/ 1399:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -7816,30 +7824,30 @@ const createExpressionState = exports.cr
  */
 
 function update(state = createExpressionState(), action) {
   switch (action.type) {
     case "ADD_EXPRESSION":
       if (action.expressionError) {
         return state.set("expressionError", !!action.expressionError);
       }
-      return appendToList(state, ["expressions"], {
+      return appendExpressionToList(state, {
         input: action.input,
         value: null,
         updating: true
       });
     case "UPDATE_EXPRESSION":
       const key = action.expression.input;
-      return updateItemInList(state, ["expressions"], key, {
+      return updateExpressionInList(state, key, {
         input: action.input,
         value: null,
         updating: true
       }).set("expressionError", !!action.expressionError);
     case "EVALUATE_EXPRESSION":
-      return updateItemInList(state, ["expressions"], action.input, {
+      return updateExpressionInList(state, action.input, {
         input: action.input,
         value: action.value,
         updating: false
       });
     case "DELETE_EXPRESSION":
       return deleteExpression(state, action.input);
     case "CLEAR_EXPRESSION_ERROR":
       return state.set("expressionError", false);
@@ -7854,71 +7862,71 @@ function update(state = createExpression
   return state;
 }
 
 function travelTo(state, action) {
   const { expressions } = action.data;
   if (!expressions) {
     return state;
   }
-  return expressions.reduce((finalState, previousState) => updateItemInList(finalState, ["expressions"], previousState.input, {
+  return expressions.reduce((finalState, previousState) => updateExpressionInList(finalState, previousState.input, {
     input: previousState.input,
     value: previousState.value,
     updating: false
   }), state);
 }
 
 function restoreExpressions() {
   const exprs = _prefs.prefs.expressions;
   if (exprs.length == 0) {
     return;
   }
   return exprs;
 }
 
-function storeExpressions(state) {
-  const expressions = state.getIn(["expressions"]).map(expression => (0, _lodash.omit)(expression, "value")).toJS();
-
-  _prefs.prefs.expressions = expressions;
-}
-
-function appendToList(state, path, value) {
-  const newState = state.updateIn(path, () => {
-    return state.getIn(path).push(value);
-  });
+function storeExpressions({ expressions }) {
+  _prefs.prefs.expressions = expressions.map(expression => (0, _lodash.omit)(expression, "value")).toJS();
+}
+
+function appendExpressionToList(state, value) {
+  const newState = state.update("expressions", () => {
+    return state.expressions.push(value);
+  });
+
   storeExpressions(newState);
   return newState;
 }
 
-function updateItemInList(state, path, key, value) {
-  const newState = state.updateIn(path, () => {
-    const list = state.getIn(path);
+function updateExpressionInList(state, key, value) {
+  const newState = state.update("expressions", () => {
+    const list = state.expressions;
     const index = list.findIndex(e => e.input == key);
     return list.update(index, () => value);
   });
+
   storeExpressions(newState);
   return newState;
 }
 
 function deleteExpression(state, input) {
   const index = getExpressions({ expressions: state }).findIndex(e => e.input == input);
   const newState = state.deleteIn(["expressions", index]);
   storeExpressions(newState);
   return newState;
 }
 
 const getExpressionsWrapper = state => state.expressions;
 
-const getExpressions = exports.getExpressions = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.get("expressions"));
+const getExpressions = exports.getExpressions = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressions);
 
 function getExpression(state, input) {
   return getExpressions(state).find(exp => exp.input == input);
 }
 
-const getExpressionError = exports.getExpressionError = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.get("expressionError"));
+const getExpressionError = exports.getExpressionError = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressionError);
 
 exports.default = update;
 
 /***/ }),
 
 /***/ 1418:
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -8113,17 +8121,17 @@ function updateAllBreakpoints(state, act
   });
   return state;
 }
 
 function removeBreakpoint(state, action) {
   const { breakpoint } = action;
 
   const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location);
-  const pendingBp = state.getIn(["pendingBreakpoints", locationId]);
+  const pendingBp = state.pendingBreakpoints.get(locationId);
 
   if (!pendingBp && action.status == "start") {
     return state.set("pendingBreakpoints", I.Map());
   }
 
   return state.deleteIn(["pendingBreakpoints", locationId]);
 }
 
@@ -8439,17 +8447,17 @@ function update(state = createFileSearch
 
     case "UPDATE_SEARCH_RESULTS":
       {
         return state.set("searchResults", action.results);
       }
 
     case "TOGGLE_FILE_SEARCH_MODIFIER":
       {
-        const actionVal = !state.getIn(["modifiers", action.modifier]);
+        const actionVal = !state.modifiers[action.modifier];
 
         if (action.modifier == "caseSensitive") {
           _prefs.prefs.fileSearchCaseSensitive = actionVal;
         }
 
         if (action.modifier == "wholeWord") {
           _prefs.prefs.fileSearchWholeWord = actionVal;
         }
@@ -8466,25 +8474,25 @@ function update(state = createFileSearch
         return state;
       }
   }
 }
 
 // NOTE: we'd like to have the app state fully typed
 // https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185
 function getFileSearchQuery(state) {
-  return state.fileSearch.get("query");
+  return state.fileSearch.query;
 }
 
 function getFileSearchModifiers(state) {
-  return state.fileSearch.get("modifiers");
+  return state.fileSearch.modifiers;
 }
 
 function getFileSearchResults(state) {
-  return state.fileSearch.get("searchResults");
+  return state.fileSearch.searchResults;
 }
 
 exports.default = update;
 
 /***/ }),
 
 /***/ 1423:
 /***/ (function(module, exports, __webpack_require__) {
@@ -10042,16 +10050,20 @@ exports.default = ResultList; /* This So
 
 ResultList.defaultProps = {
   size: "small",
   role: "listbox"
 };
 
 var _initialiseProps = function () {
   this.renderListItem = (item, index) => {
+    if (item.value === "/" && item.title === "") {
+      item.title = "(index)";
+    }
+
     const { selectItem, selected } = this.props;
     const props = {
       onClick: event => selectItem(event, item, index),
       key: `${item.id}${item.value}${index}`,
       ref: String(index),
       title: item.value,
       "aria-labelledby": `${item.id}-title`,
       "aria-describedby": `${item.id}-subtitle`,
@@ -25013,17 +25025,17 @@ function _interopRequireDefault(obj) { r
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 class Tabs extends _react.PureComponent {
 
   constructor(props) {
     super(props);
 
     this.renderDropdownSource = source => {
-      const { selectSource } = this.props;
+      const { selectSpecificSource } = this.props;
       const filename = (0, _source.getFilename)(source.toJS());
 
       const onClick = () => selectSpecificSource(source.id);
       return _react2.default.createElement(
         "li",
         { key: source.id, onClick: onClick },
         _react2.default.createElement("img", { className: `dropdown-icon ${this.getIconClass(source)}` }),
         filename
@@ -30226,21 +30238,16 @@ function createLocation({
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* 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/>. */
-
 exports.getExtra = getExtra;
 exports.updatePreview = updatePreview;
 exports.setPreview = setPreview;
 exports.clearPreview = clearPreview;
 
 var _ast = __webpack_require__(1638);
 
 var _editor = __webpack_require__(1358);
@@ -30260,17 +30267,19 @@ var _expressions = __webpack_require__(1
 var _lodash = __webpack_require__(2);
 
 async function getReactProps(evaluate) {
   const reactDisplayName = await evaluate("this.hasOwnProperty('_reactInternalFiber') ? " + "this._reactInternalFiber.type.name : " + "this._reactInternalInstance.getName()");
 
   return {
     displayName: reactDisplayName.result
   };
-}
+} /* 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/>. */
 
 async function getImmutableProps(expression, evaluate) {
   const immutableEntries = await evaluate((exp => `${exp}.toJS()`)(expression));
 
   const immutableType = await evaluate((exp => `${exp}.constructor.name`)(expression));
 
   return {
     type: immutableType.result,
@@ -30378,19 +30387,17 @@ function setPreview(expression, location
   return async ({ dispatch, getState, client, sourceMaps }) => {
     await dispatch({
       type: "SET_PREVIEW",
       [_promise.PROMISE]: async function () {
         const source = (0, _selectors.getSelectedSource)(getState());
 
         const sourceId = source.get("id");
         if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
-          const generatedLocation = await sourceMaps.getGeneratedLocation(_extends({}, location.start, { sourceId }), source.toJS());
-
-          expression = await (0, _expressions.getMappedExpression)({ sourceMaps, getState }, generatedLocation, expression);
+          expression = await dispatch((0, _expressions.getMappedExpression)(expression));
         }
 
         const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
         if (!selectedFrame) {
           return;
         }
 
         const { result } = await client.evaluateInFrame(selectedFrame.id, expression);
@@ -31528,16 +31535,18 @@ var _extends = Object.assign || function
 /**
  * Redux actions for the sources state
  * @module actions/sources
  */
 
 exports.selectSourceURL = selectSourceURL;
 exports.selectSource = selectSource;
 exports.selectLocation = selectLocation;
+exports.selectSpecificLocation = selectSpecificLocation;
+exports.selectSpecificSource = selectSpecificSource;
 exports.jumpToMappedLocation = jumpToMappedLocation;
 exports.jumpToMappedSelectedLocation = jumpToMappedSelectedLocation;
 
 var _devtoolsSourceMap = __webpack_require__(1360);
 
 var _ast = __webpack_require__(1399);
 
 var _ui = __webpack_require__(1385);
@@ -31608,56 +31617,113 @@ function selectSource(sourceId) {
 function selectLocation(location) {
   return async ({ dispatch, getState, client }) => {
     if (!client) {
       // No connection, do nothing. This happens when the debugger is
       // shut down too fast and it tries to display a default source.
       return;
     }
 
-    const source = (0, _selectors.getSource)(getState(), location.sourceId);
-    if (!source) {
+    const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId);
+    if (!sourceRecord) {
       // If there is no source we deselect the current selected source
       return dispatch({ type: "CLEAR_SELECTED_SOURCE" });
     }
 
     const activeSearch = (0, _selectors.getActiveSearch)(getState());
     if (activeSearch !== "file") {
       dispatch((0, _ui.closeActiveSearch)());
     }
 
-    dispatch((0, _tabs.addTab)(source.toJS(), 0));
-
+    const source = sourceRecord.toJS();
+
+    dispatch((0, _tabs.addTab)(source, 0));
     dispatch({
       type: "SELECT_SOURCE",
-      source: source.toJS(),
+      source,
       location
     });
 
-    await dispatch((0, _loadSourceText.loadSourceText)(source));
+    await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord));
     const selectedSource = (0, _selectors.getSelectedSource)(getState());
     if (!selectedSource) {
       return;
     }
 
-    const sourceId = selectedSource.get("id");
+    const sourceId = selectedSource.id;
+
     if (_prefs.prefs.autoPrettyPrint && !(0, _selectors.getPrettySource)(getState(), sourceId) && (0, _source.shouldPrettyPrint)(selectedSource) && (0, _source.isMinified)(selectedSource)) {
       await dispatch((0, _prettyPrint.togglePrettyPrint)(sourceId));
       dispatch((0, _tabs.closeTab)(source.url));
     }
 
     dispatch((0, _ast.setSymbols)(sourceId));
     dispatch((0, _ast.setOutOfScopeLocations)());
   };
 }
 
 /**
  * @memberof actions/sources
  * @static
  */
+function selectSpecificLocation(location) {
+  return async ({ dispatch, getState, client }) => {
+    if (!client) {
+      // No connection, do nothing. This happens when the debugger is
+      // shut down too fast and it tries to display a default source.
+      return;
+    }
+
+    const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId);
+    if (!sourceRecord) {
+      // If there is no source we deselect the current selected source
+      return dispatch({ type: "CLEAR_SELECTED_SOURCE" });
+    }
+
+    const activeSearch = (0, _selectors.getActiveSearch)(getState());
+    if (activeSearch !== "file") {
+      dispatch((0, _ui.closeActiveSearch)());
+    }
+
+    const source = sourceRecord.toJS();
+
+    dispatch((0, _tabs.addTab)(source, 0));
+    dispatch({
+      type: "SELECT_SOURCE",
+      source,
+      location
+    });
+
+    await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord));
+    const selectedSource = (0, _selectors.getSelectedSource)(getState());
+    if (!selectedSource) {
+      return;
+    }
+
+    const sourceId = selectedSource.id;
+    dispatch((0, _ast.setSymbols)(sourceId));
+    dispatch((0, _ast.setOutOfScopeLocations)());
+  };
+}
+
+/**
+ * @memberof actions/sources
+ * @static
+ */
+function selectSpecificSource(sourceId) {
+  return async ({ dispatch }) => {
+    const location = (0, _location.createLocation)({ sourceId });
+    return await dispatch(selectSpecificLocation(location));
+  };
+}
+
+/**
+ * @memberof actions/sources
+ * @static
+ */
 function jumpToMappedLocation(location) {
   return async function ({ dispatch, getState, client, sourceMaps }) {
     if (!client) {
       return;
     }
 
     const source = (0, _selectors.getSource)(getState(), location.sourceId);
     let pairedLocation;
@@ -33687,17 +33753,17 @@ class Tab extends _react.PureComponent {
 
   isSourceSearchEnabled() {
     return this.props.activeSearch === "source";
   }
 
   render() {
     const {
       selectedSource,
-      selectSource,
+      selectSpecificSource,
       closeTab,
       source,
       sourceMetaData
     } = this.props;
     const src = source.toJS();
     const filename = (0, _source.getFilename)(src);
     const sourceId = source.id;
     const active = selectedSource && sourceId == selectedSource.get("id") && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled();
@@ -33713,17 +33779,17 @@ class Tab extends _react.PureComponent {
       e.preventDefault();
       e.stopPropagation();
 
       // Accommodate middle click to close tab
       if (e.button === 1) {
         return closeTab(source.url);
       }
 
-      return selectSource(sourceId);
+      return selectSpecificSource(sourceId);
     }
 
     const className = (0, _classnames2.default)("source-tab", {
       active,
       pretty: isPrettyCode
     });
 
     return _react2.default.createElement(
@@ -33855,18 +33921,16 @@ function updateTree({
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 
 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
 
 exports.setupHelper = setupHelper;
 
-var _redux = __webpack_require__(3593);
-
 var _timings = __webpack_require__(1657);
 
 var timings = _interopRequireWildcard(_timings);
 
 var _prefs = __webpack_require__(226);
 
 var _devtoolsConfig = __webpack_require__(1355);
 
@@ -33912,20 +33976,18 @@ function getCM() {
 function _formatPausePoints(dbg, url) {
   const source = dbg.helpers.findSource(url);
   const pausePoints = dbg.selectors.getPausePoints(source);
   console.log((0, _pausePoints.formatPausePoints)(source.text, pausePoints));
 }
 
 function setupHelper(obj) {
   const selectors = bindSelectors(obj);
-  const actions = (0, _redux.bindActionCreators)(obj.actions, obj.store.dispatch);
   const dbg = _extends({}, obj, {
     selectors,
-    actions,
     prefs: _prefs.prefs,
     features: _prefs.features,
     timings,
     getCM,
     helpers: {
       findSource: url => findSource(dbg, url),
       evaluate: (expression, cbk) => evaluate(dbg, expression, cbk),
       sendPacketToThread: (packet, cbk) => sendPacketToThread(dbg, packet, cbk),
--- a/devtools/client/debugger/new/panel.js
+++ b/devtools/client/debugger/new/panel.js
@@ -111,16 +111,20 @@ DebuggerPanel.prototype = {
 
     frames.forEach(frame => {
       frame.actor = frame.id;
     });
 
     return { frames, selected };
   },
 
+  getMappedExpression(expression) {
+    return this._actions.getMappedExpression(expression);
+  },
+
   isPaused() {
     return this._selectors.isPaused(this._getState());
   },
 
   selectSource(url, line) {
     this._actions.selectSourceURL(url, { location: { line } });
   },
 
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -779,31 +779,33 @@ const {
 } = __webpack_require__(1389);
 
 const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1363);
 
 const dispatcher = new WorkerDispatcher();
 
 const getOriginalURLs = dispatcher.task("getOriginalURLs");
 const getGeneratedLocation = dispatcher.task("getGeneratedLocation");
+const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations");
 const getOriginalLocation = dispatcher.task("getOriginalLocation");
 const getLocationScopes = dispatcher.task("getLocationScopes");
 const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
 const applySourceMap = dispatcher.task("applySourceMap");
 const clearSourceMaps = dispatcher.task("clearSourceMaps");
 const hasMappedSource = dispatcher.task("hasMappedSource");
 
 module.exports = {
   originalToGeneratedId,
   generatedToOriginalId,
   isGeneratedId,
   isOriginalId,
   hasMappedSource,
   getOriginalURLs,
   getGeneratedLocation,
+  getAllGeneratedLocations,
   getOriginalLocation,
   getLocationScopes,
   getOriginalSourceText,
   applySourceMap,
   clearSourceMaps,
   startSourceMapWorker: dispatcher.start.bind(dispatcher),
   stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
 };
@@ -1155,16 +1157,17 @@ function trimUrlQuery(url) {
 
   return url.slice(0, q);
 }
 
 // Map suffix to content type.
 const contentMap = {
   "js": "text/javascript",
   "jsm": "text/javascript",
+  "mjs": "text/javascript",
   "ts": "text/typescript",
   "tsx": "text/typescript-jsx",
   "jsx": "text/jsx",
   "coffee": "text/coffeescript",
   "elm": "text/elm",
   "cljs": "text/x-clojure"
 };
 
@@ -21281,37 +21284,46 @@ function getFirstExpression(ast) {
   if (statements.length == 0) {
     return null;
   }
 
   return statements[0].expression;
 }
 
 function mapOriginalExpression(expression, mappings) {
+  let didReplace = false;
+
   const ast = (0, _ast.parseScript)(expression);
   t.traverse(ast, (node, ancestors) => {
     const parent = ancestors[ancestors.length - 1];
     if (!parent) {
       return;
     }
 
     const parentNode = parent.node;
     if (t.isIdentifier(node) && t.isReferenced(node, parentNode)) {
       if (mappings.hasOwnProperty(node.name)) {
         const mapping = mappings[node.name];
-        if (mapping) {
+        if (mapping && mapping !== node.name) {
           const mappingNode = getFirstExpression((0, _ast.parseScript)(mapping));
-
           replaceNode(ancestors, mappingNode);
+
+          didReplace = true;
         }
       }
     }
   });
 
-  return (0, _generator2.default)(ast, { concise: true }).code;
+  if (!didReplace) {
+    // Avoid the extra code generation work and also avoid potentially
+    // reformatting the user's code unnecessarily.
+    return expression;
+  }
+
+  return (0, _generator2.default)(ast).code;
 }
 
 /***/ }),
 
 /***/ 3624:
 /***/ (function(module, exports, __webpack_require__) {
 
 var baseIteratee = __webpack_require__(814),
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-preview.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-preview.js
@@ -80,42 +80,42 @@ add_task(async function() {
   await pushPref("devtools.debugger.features.map-scopes", true);
 
   const dbg = await initDebugger("doc-babel.html");
 
   await breakpointPreviews(dbg, "for-of", { line: 5, column: 4 }, [
     {
       line: 5,
       column: 7,
-      expression: "doThing;",
+      expression: "doThing",
       result: "doThing(arg)",
     },
     {
       line: 5,
       column: 12,
-      expression: "x;",
+      expression: "x",
       result: "1",
     },
     {
       line: 8,
       column: 16,
-      expression: "doThing;",
+      expression: "doThing",
       result: "doThing(arg)",
     },
   ]);
 
   await breakpointPreviews(dbg, "shadowed-vars", { line: 18, column: 6 }, [
     // These aren't what the user would expect, but we test them anyway since
     // they reflect what this actually returns. These shadowed bindings read
     // the binding closest to the current frame's scope even though their
     // actual value is different.
     {
       line: 2,
       column: 9,
-      expression: "aVar;",
+      expression: "aVar",
       result: '"var3"',
     },
     {
       line: 3,
       column: 9,
       expression: "_aLet2;",
       result: '"let3"',
     },
@@ -123,17 +123,17 @@ add_task(async function() {
       line: 4,
       column: 11,
       expression: "_aConst2;",
       result: '"const3"',
     },
     {
       line: 10,
       column: 11,
-      expression: "aVar;",
+      expression: "aVar",
       result: '"var3"',
     },
     {
       line: 11,
       column: 11,
       expression: "_aLet2;",
       result: '"let3"',
     },
@@ -143,17 +143,17 @@ add_task(async function() {
       expression: "_aConst2;",
       result: '"const3"',
     },
 
     // These actually result in the values the user would expect.
     {
       line: 14,
       column: 13,
-      expression: "aVar;",
+      expression: "aVar",
       result: '"var3"',
     },
     {
       line: 15,
       column: 13,
       expression: "_aLet2;",
       result: '"let3"',
     },
@@ -188,17 +188,17 @@ add_task(async function() {
       line: 25,
       column: 16,
       expression: "_mod4.original;",
       result: '"an-original"',
     },
     {
       line: 26,
       column: 16,
-      expression: "aNamespace;",
+      expression: "aNamespace",
       fields: [
         ['aNamed', 'a-named'],
         ['default', 'a-default'],
       ],
     },
     {
       line: 31,
       column: 20,
@@ -221,16 +221,16 @@ add_task(async function() {
       line: 34,
       column: 20,
       expression: "_mod9.original;",
       result: '"an-original2"',
     },
     {
       line: 35,
       column: 20,
-      expression: "aNamespace2;",
+      expression: "aNamespace2",
       fields: [
         ['aNamed', 'a-named2'],
         ['default', 'a-default2'],
       ],
     },
   ]);
 });
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1006,17 +1006,16 @@ public:
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 private:
     void SetEnabled(const char* funcName, GLenum cap, bool enabled);
 public:
     void Disable(GLenum cap) { SetEnabled("disabled", cap, false); }
     void Enable(GLenum cap) { SetEnabled("enabled", cap, true); }
     bool GetStencilBits(GLint* const out_stencilBits) const;
-    bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val);
     virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
 
     void GetParameter(JSContext* cx, GLenum pname,
                       JS::MutableHandle<JS::Value> retval, ErrorResult& rv)
     {
         retval.set(GetParameter(cx, pname, rv));
     }
 
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -69,97 +69,16 @@ WebGLContext::GetStencilBits(GLint* cons
         }
     } else if (mOptions.stencil) {
         *out_stencilBits = 8;
     }
 
     return true;
 }
 
-bool
-WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val)
-{
-    if (mBoundDrawFramebuffer) {
-        if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
-            return false;
-    }
-
-    if (!mBoundDrawFramebuffer) {
-        switch (pname) {
-        case LOCAL_GL_RED_BITS:
-        case LOCAL_GL_GREEN_BITS:
-        case LOCAL_GL_BLUE_BITS:
-            *out_val = 8;
-            break;
-
-        case LOCAL_GL_ALPHA_BITS:
-            *out_val = (mOptions.alpha ? 8 : 0);
-            break;
-
-        case LOCAL_GL_DEPTH_BITS:
-            *out_val = (mOptions.depth ? 24 : 0);
-            break;
-
-        case LOCAL_GL_STENCIL_BITS:
-            *out_val = (mOptions.stencil ? 8 : 0);
-            break;
-
-        default:
-            MOZ_CRASH("GFX: bad pname");
-        }
-        return true;
-    }
-
-    if (!gl->IsCoreProfile()) {
-        gl->fGetIntegerv(pname, out_val);
-        return true;
-    }
-
-    GLenum fbAttachment = 0;
-    GLenum fbPName = 0;
-    switch (pname) {
-    case LOCAL_GL_RED_BITS:
-        fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
-        break;
-
-    case LOCAL_GL_GREEN_BITS:
-        fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
-        break;
-
-    case LOCAL_GL_BLUE_BITS:
-        fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
-        break;
-
-    case LOCAL_GL_ALPHA_BITS:
-        fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
-        break;
-
-    case LOCAL_GL_DEPTH_BITS:
-        fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
-        break;
-
-    case LOCAL_GL_STENCIL_BITS:
-        fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT;
-        fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
-        break;
-
-    default:
-        MOZ_CRASH("GFX: bad pname");
-    }
-
-    gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment,
-                                             fbPName, out_val);
-    return true;
-}
-
 JS::Value
 WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
 {
     const char funcName[] = "getParameter";
 
     if (IsContextLost())
         return JS::NullValue();
 
@@ -392,22 +311,82 @@ WebGLContext::GetParameter(JSContext* cx
         }
 
         case LOCAL_GL_RED_BITS:
         case LOCAL_GL_GREEN_BITS:
         case LOCAL_GL_BLUE_BITS:
         case LOCAL_GL_ALPHA_BITS:
         case LOCAL_GL_DEPTH_BITS:
         case LOCAL_GL_STENCIL_BITS: {
-            // Deprecated and removed in GL Core profiles, so special handling required.
-            GLint val;
-            if (!GetChannelBits(funcName, pname, &val))
-                return JS::NullValue();
+            const auto format = [&]() -> const webgl::FormatInfo* {
+                if (mBoundDrawFramebuffer) {
+                    const auto& fb = *mBoundDrawFramebuffer;
+                    const auto& attachment = [&]() -> const auto& {
+                        switch (pname) {
+                        case LOCAL_GL_DEPTH_BITS:
+                            return fb.AnyDepthAttachment();
+
+                        case LOCAL_GL_STENCIL_BITS:
+                            return fb.AnyStencilAttachment();
+
+                        default:
+                            return fb.ColorAttachment0();
+                        }
+                    }();
+                    if (!attachment.HasImage())
+                        return nullptr;
+                    return attachment.Format()->format;
+                }
+
+                auto effFormat = webgl::EffectiveFormat::RGB8;
+                switch (pname) {
+                case LOCAL_GL_DEPTH_BITS:
+                    if (mOptions.depth) {
+                        effFormat = webgl::EffectiveFormat::DEPTH24_STENCIL8;
+                    }
+                    break;
 
-            return JS::Int32Value(val);
+                case LOCAL_GL_STENCIL_BITS:
+                    if (mOptions.stencil) {
+                        effFormat = webgl::EffectiveFormat::DEPTH24_STENCIL8;
+                    }
+                    break;
+
+                default:
+                    if (mOptions.alpha) {
+                        effFormat = webgl::EffectiveFormat::RGBA8;
+                    }
+                    break;
+                }
+                return webgl::GetFormat(effFormat);
+            }();
+            int32_t ret = 0;
+            if (format) {
+                switch (pname) {
+                case LOCAL_GL_RED_BITS:
+                    ret = format->r;
+                    break;
+                case LOCAL_GL_GREEN_BITS:
+                    ret = format->g;
+                    break;
+                case LOCAL_GL_BLUE_BITS:
+                    ret = format->b;
+                    break;
+                case LOCAL_GL_ALPHA_BITS:
+                    ret = format->a;
+                    break;
+                case LOCAL_GL_DEPTH_BITS:
+                    ret = format->d;
+                    break;
+                case LOCAL_GL_STENCIL_BITS:
+                    ret = format->s;
+                    break;
+                }
+            }
+            return JS::Int32Value(ret);
         }
 
         case LOCAL_GL_MAX_TEXTURE_SIZE:
             return JS::Int32Value(mGLMaxTextureSize);
 
         case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
             return JS::Int32Value(mGLMaxCubeMapTextureSize);
 
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -33,27 +33,28 @@ namespace gl {
 
 class WebGLFBAttachPoint final
 {
     friend class WebGLFramebuffer;
 public:
     WebGLFramebuffer* const mFB;
     const GLenum mAttachmentPoint;
 
-protected:
+private:
     WebGLRefPtr<WebGLTexture> mTexturePtr;
     WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
     TexImageTarget mTexImageTarget;
     GLint mTexImageLayer;
     uint32_t mTexImageLevel;
 
     ////
 
     WebGLFBAttachPoint();
     WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
+    explicit WebGLFBAttachPoint(WebGLFBAttachPoint&) = default; // Make this private.
 
 public:
     ~WebGLFBAttachPoint();
 
     ////
 
     void Unlink();
 
@@ -253,16 +254,32 @@ public:
     GETTER(StencilAttachment)
     GETTER(DepthStencilAttachment)
     GETTER(ColorDrawBuffers)
     GETTER(ColorReadBuffer)
     GETTER(ResolvedCompleteData)
 
 #undef GETTER
 
+    const auto& ColorAttachment0() const {
+        return mColorAttachments[0];
+    }
+
+    const auto& AnyDepthAttachment() const {
+        if (mDepthStencilAttachment.IsDefined())
+            return mDepthStencilAttachment;
+        return mDepthAttachment;
+    }
+
+    const auto& AnyStencilAttachment() const {
+        if (mDepthStencilAttachment.IsDefined())
+            return mDepthStencilAttachment;
+        return mStencilAttachment;
+    }
+
     ////////////////
     // Invalidation
 
     bool IsResolvedComplete() const { return bool(mResolvedCompleteData); }
     void InvalidateFramebufferStatus(const char* funcName);
     void RefreshResolvedData();
 
     ////////////////
--- a/dom/html/test/forms/test_input_date_key_events.html
+++ b/dom/html/test/forms/test_input_date_key_events.html
@@ -221,14 +221,23 @@ function test() {
     elem.focus();
     elem.value = initialVal;
     sendKeys(keys);
     is(elem.value, expectedVal,
        "Test with " + keys + ", result should be " + expectedVal);
     elem.value = "";
     elem.blur();
   }
+
+  function chromeListener(e) {
+    ok(false, "Picker should not be opened when dispatching untrusted click.");
+  }
+  SpecialPowers.addChromeEventListener("MozOpenDateTimePicker",
+    chromeListener);
+  input.click();
+  SpecialPowers.removeChromeEventListener("MozOpenDateTimePicker",
+    chromeListener);
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/interfaces/payments/nsIPaymentRequest.idl
+++ b/dom/interfaces/payments/nsIPaymentRequest.idl
@@ -57,17 +57,17 @@ interface nsIPaymentDetails : nsISupport
 {
   readonly attribute AString id;
   readonly attribute nsIPaymentItem totalItem;
   readonly attribute nsIArray displayItems;
   readonly attribute nsIArray shippingOptions;
   readonly attribute nsIArray modifiers;
   readonly attribute AString error;
 
-  void update(in nsIPaymentDetails aDetails);
+  void update(in nsIPaymentDetails aDetails, in boolean aRequestShipping);
 };
 
 [scriptable, builtinclass, uuid(d53f9f20-138e-47cc-9fd5-db16a3f6d301)]
 interface nsIPaymentOptions : nsISupports
 {
   readonly attribute boolean requestPayerName;
   readonly attribute boolean requestPayerEmail;
   readonly attribute boolean requestPayerPhone;
--- a/dom/payments/PaymentRequestData.cpp
+++ b/dom/payments/PaymentRequestData.cpp
@@ -470,17 +470,17 @@ PaymentDetails::GetModifiers(nsIArray** 
 NS_IMETHODIMP
 PaymentDetails::GetError(nsAString& aError)
 {
   aError = mError;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PaymentDetails::Update(nsIPaymentDetails* aDetails)
+PaymentDetails::Update(nsIPaymentDetails* aDetails, const bool aRequestShipping)
 {
   MOZ_ASSERT(aDetails);
   /*
    * According to the spec [1], update the attributes if they present in new
    * details (i.e., PaymentDetailsUpdate); otherwise, keep original value.
    * Note |id| comes only from initial details (i.e., PaymentDetailsInit) and
    * |error| only from new details.
    *
@@ -496,22 +496,22 @@ PaymentDetails::Update(nsIPaymentDetails
   rv = aDetails->GetDisplayItems(getter_AddRefs(displayItems));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (displayItems) {
     mDisplayItems = displayItems;
   }
 
-  nsCOMPtr<nsIArray> shippingOptions;
-  rv = aDetails->GetShippingOptions(getter_AddRefs(shippingOptions));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (shippingOptions) {
+  if (aRequestShipping) {
+    nsCOMPtr<nsIArray> shippingOptions;
+    rv = aDetails->GetShippingOptions(getter_AddRefs(shippingOptions));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     mShippingOptions = shippingOptions;
   }
 
   nsCOMPtr<nsIArray> modifiers;
   rv = aDetails->GetModifiers(getter_AddRefs(modifiers));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -673,17 +673,22 @@ PaymentRequest::GetPaymentOptions(nsIPay
   options.forget(aPaymentOptions);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PaymentRequest::UpdatePaymentDetails(nsIPaymentDetails* aPaymentDetails)
 {
   MOZ_ASSERT(aPaymentDetails);
-  return mPaymentDetails->Update(aPaymentDetails);
+  bool requestShipping;
+  nsresult rv = mPaymentOptions->GetRequestShipping(&requestShipping);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return mPaymentDetails->Update(aPaymentDetails, requestShipping);
 }
 
 NS_IMETHODIMP
 PaymentRequest::SetCompleteStatus(const nsAString& aCompleteStatus)
 {
   mCompleteStatus = aCompleteStatus;
   return NS_OK;
 }
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/Bug1443914ChromeScript.js
@@ -0,0 +1,80 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+
+function emitTestFail(message) {
+  sendAsyncMessage("test-fail", message);
+}
+function emitTestPass(message) {
+  sendAsyncMessage("test-pass", message);
+}
+
+const shippingAddress = Cc["@mozilla.org/dom/payments/payment-address;1"].
+                           createInstance(Ci.nsIPaymentAddress);
+const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+address.data = "Easton Ave";
+addressLine.appendElement(address);
+shippingAddress.init("USA",              // country
+                     addressLine,        // address line
+                     "CA",               // region
+                     "San Bruno",        // city
+                     "Test locality",    // dependent locality
+                     "94066",            // postal code
+                     "123456",           // sorting code
+                     "en",               // language code
+                     "Testing Org",      // organization
+                     "Bill A. Pacheco",  // recipient
+                     "+1-434-441-3879"); // phone
+
+const TestingUIService = {
+  showPayment: function(requestId) {
+    paymentSrv.changeShippingAddress(requestId, shippingAddress);
+  },
+  abortPayment: function(requestId) {
+  },
+  completePayment: function(requestId) {
+    let request = paymentSrv.getPaymentRequestById(requestId);
+    let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
+                           createInstance(Ci.nsIPaymentCompleteActionResponse);
+    completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
+    paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
+  },
+  updatePayment: function(requestId) {
+    let request = paymentSrv.getPaymentRequestById(requestId);
+    if (request.shippingOptions != null) {
+      emitTestFail("request.shippingOptions should be null");
+    } else {
+      emitTestPass("request.shippingOptions should be null");
+    }
+    const showResponseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                                createInstance(Ci.nsIGeneralResponseData);
+    showResponseData.initData({});
+    const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
+                            createInstance(Ci.nsIPaymentShowActionResponse);
+    showResponse.init(requestId,
+                      Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
+                      "testing-payment-method",   // payment method
+                      showResponseData,           // payment method data
+                      "Bill A. Pacheco",          // payer name
+                      "",                         // payer email
+                      "");                        // payer phone
+    paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
+};
+
+addMessageListener("set-checking-shipping-options-ui-service", function() {
+  paymentSrv.setTestingUIService(TestingUIService.QueryInterface(Ci.nsIPaymentUIService));
+});
+
+addMessageListener("teardown", function() {
+  paymentSrv.cleanup();
+  paymentSrv.setTestingUIService(null);
+  sendAsyncMessage('teardown-complete');
+});
--- a/dom/payments/test/mochitest.ini
+++ b/dom/payments/test/mochitest.ini
@@ -1,28 +1,30 @@
 [DEFAULT]
 # skip-if !e10s will be removed once non-e10s is supported
 skip-if = !e10s
 scheme = https
 support-files =
   simple_payment_request.html
   echo_payment_request.html
   BasiccardChromeScript.js
+  Bug1443914ChromeScript.js
   ConstructorChromeScript.js
   CurrencyAmountValidationChromeScript.js
   GeneralChromeScript.js
   PMIValidationChromeScript.js
   ShowPaymentChromeScript.js
   RequestShippingChromeScript.js
 
 [test_abortPayment.html]
 run-if = nightly_build # Bug 1390018: Depends on the Nightly-only UI service
 [test_basiccard.html]
 [test_block_none10s.html]
 skip-if = e10s # Bug 1408250: Don't expose PaymentRequest Constructor in non-e10s
+[test_bug1443914.html]
 [test_canMakePayment.html]
 run-if = nightly_build # Bug 1390737: Depends on the Nightly-only UI service
 [test_constructor.html]
 [test_currency_amount_validation.html]
 [test_payment-request-in-iframe.html]
 [test_pmi_validation.html]
 [test_requestShipping.html]
 [test_showPayment.html]
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/test_bug1443914.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1443914
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1443914</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript">
+
+  "use strict";
+  SimpleTest.waitForExplicitFinish();
+
+  var gUrl = SimpleTest.getTestFileURL('Bug1443914ChromeScript.js');
+  var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+  function testFailHandler(message) {
+    ok(false, message);
+  }
+  function testPassHandler(message) {
+    ok(true, message);
+  }
+  gScript.addMessageListener("test-fail", testFailHandler);
+  gScript.addMessageListener("test-pass", testPassHandler);
+
+  // testing data declation
+  const defaultMethods = [{
+    supportedMethods: "basic-card",
+    data: {
+      supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
+                          'diners', 'jcb', 'mir',
+      ],
+      supportedTypes: ['prepaid', 'debit', 'credit'],
+    },
+  }, {
+    supportedMethods: "testing-payment-method",
+  }];
+
+  const defaultDetails = {
+    id: "test payment",
+    total: {
+      label: "Total",
+      amount: {
+        currency: "USD",
+        value: "1.00"
+      }
+    },
+    shippingOptions: [
+      {
+        id: "NormalShipping",
+        label: "NormalShipping",
+        amount: {
+          currency: "USD",
+          value: "10.00"
+        },
+        selected: false,
+      },
+    ],
+  };
+
+  const defaultOptions = {
+    requestPayerName: true,
+    requestPayerEmail: false,
+    reqeustPayerPhone: false,
+    requestShipping: true,
+    shippingType: "shipping"
+  };
+
+  const updateDetails = {
+    total: {
+      label: "Total",
+      amount: {
+        currency: "USD",
+        value: "1.00"
+      }
+    },
+    error: "",
+  };
+  // testing function main body
+  function test_bug1443914() {
+    gScript.sendAsyncMessage("set-checking-shipping-options-ui-service");
+    return new Promise((resolve, reject) => {
+      const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
+      const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
+      request.addEventListener("shippingaddresschange", (event) => {
+        event.updateWith(updateDetails);
+      });
+      request.addEventListener("shippingoptionchange", (event) => {
+        event.updateWith(updateDetails);
+      });
+      request.show().then(response => {
+        response.complete("success").then(() => {
+	  resolve();
+	}).catch(error => {
+	  ok(false, "Unexpected error: " + error.name);
+	  resolve();
+	});
+      }).catch(error => {
+        ok(false, "Unexpected error: " + error.name);
+	resolve();
+      }).finally(handler.destruct);
+    });
+  }
+
+  function teardown() {
+    gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
+      gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
+      gScript.removeMessageListener("test-fail", testFailHandler);
+      gScript.removeMessageListener("test-pass", testPassHandler);
+      gScript.destroy();
+      SimpleTest.finish();
+    });
+    gScript.sendAsyncMessage("teardown");
+  }
+
+  function runTests() {
+    test_bug1443914()
+    .then(teardown)
+    .catch( e => {
+      ok(false, "Unexpected error: " + e.name);
+      SimpleTest.finish();
+    });
+  }
+
+  window.addEventListener('load', function() {
+    SpecialPowers.pushPrefEnv({
+      'set': [
+        ['dom.payments.request.enabled', true],
+      ]
+    }, runTests);
+  });
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1443914">Mozilla Bug 1443914</a>
+</body>
+</html>
--- a/dom/security/test/csp/file_meta_element.html
+++ b/dom/security/test/csp/file_meta_element.html
@@ -4,22 +4,24 @@
   <meta charset="utf-8">
   <meta http-equiv="Content-Security-Policy"
         content= "img-src 'none'; script-src 'unsafe-inline'; report-uri http://www.example.com; frame-ancestors https:; sandbox allow-scripts">
   <title>Bug 663570 - Implement Content Security Policy via meta tag</title>
 </head>
 <body>
 
   <!-- try to load an image which is forbidden by meta CSP -->
-  <img id="testimage" src="http://mochi.test:8888/tests/image/test/mochitest/blue.png"></img>
+  <img id="testimage"></img>
 
   <script type="application/javascript">
     var myImg = document.getElementById("testimage");
     myImg.onload = function(e) {
       window.parent.postMessage({result: "img-loaded"}, "*");
     };
     myImg.onerror = function(e) {
       window.parent.postMessage({result: "img-blocked"}, "*");
     };
+    //Image should be tried to load only after onload/onerror event declaration.
+    myImg.src = "http://mochi.test:8888/tests/image/test/mochitest/blue.png";
   </script>
 
 </body>
 </html>
--- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp
@@ -259,16 +259,17 @@ IpcResourceUpdateQueue::AddImage(ImageKe
   mUpdates.AppendElement(layers::OpAddImage(aDescriptor, bytes, 0, key));
   return true;
 }
 
 bool
 IpcResourceUpdateQueue::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
                                      Range<uint8_t> aBytes)
 {
+  MOZ_RELEASE_ASSERT(aDescriptor.width > 0 && aDescriptor.height > 0);
   auto bytes = mWriter.Write(aBytes);
   if (!bytes.length()) {
     return false;
   }
   mUpdates.AppendElement(layers::OpAddBlobImage(aDescriptor, bytes, 0, key));
   return true;
 }
 
--- a/gfx/thebes/gfxCoreTextShaper.cpp
+++ b/gfx/thebes/gfxCoreTextShaper.cpp
@@ -13,22 +13,17 @@
 
 #include <algorithm>
 
 #include <dlfcn.h>
 
 using namespace mozilla;
 
 // standard font descriptors that we construct the first time they're needed
-CTFontDescriptorRef gfxCoreTextShaper::sDefaultFeaturesDescriptor = nullptr;
-CTFontDescriptorRef gfxCoreTextShaper::sSmallCapsDescriptor = nullptr;
-CTFontDescriptorRef gfxCoreTextShaper::sDisableLigaturesDescriptor = nullptr;
-CTFontDescriptorRef gfxCoreTextShaper::sSmallCapDisableLigDescriptor = nullptr;
-CTFontDescriptorRef gfxCoreTextShaper::sIndicFeaturesDescriptor = nullptr;
-CTFontDescriptorRef gfxCoreTextShaper::sIndicDisableLigaturesDescriptor = nullptr;
+CTFontDescriptorRef gfxCoreTextShaper::sFeaturesDescriptor[kMaxFontInstances];
 
 // Helper to create a CFDictionary with the right attributes for shaping our
 // text, including imposing the given directionality.
 CFDictionaryRef
 gfxCoreTextShaper::CreateAttrDict(bool aRightToLeft)
 {
     // Because we always shape unidirectional runs, and may have applied
     // directional overrides, we want to force a direction rather than
@@ -40,46 +35,52 @@ gfxCoreTextShaper::CreateAttrDict(bool a
         ::CFNumberCreate(kCFAllocatorDefault,
                          kCFNumberSInt16Type, &dirOverride);
     CFArrayRef dirArray =
         ::CFArrayCreate(kCFAllocatorDefault,
                         (const void **) &dirNumber, 1,
                         &kCFTypeArrayCallBacks);
     ::CFRelease(dirNumber);
     CFTypeRef attrs[] = { kCTFontAttributeName, kCTWritingDirectionAttributeName };
-    CFTypeRef values[] = { mCTFont, dirArray };
+    CFTypeRef values[] = { mCTFont[0], dirArray };
     CFDictionaryRef attrDict =
         ::CFDictionaryCreate(kCFAllocatorDefault,
                              attrs, values, ArrayLength(attrs),
                              &kCFTypeDictionaryKeyCallBacks,
                              &kCFTypeDictionaryValueCallBacks);
     ::CFRelease(dirArray);
     return attrDict;
 }
 
 gfxCoreTextShaper::gfxCoreTextShaper(gfxMacFont *aFont)
     : gfxFontShaper(aFont)
     , mAttributesDictLTR(nullptr)
     , mAttributesDictRTL(nullptr)
 {
-    // Create our CTFontRef
-    mCTFont = CreateCTFontWithFeatures(aFont->GetAdjustedSize(),
-                                       GetDefaultFeaturesDescriptor());
+    for (size_t i = 0; i < kMaxFontInstances; i++) {
+        mCTFont[i] = nullptr;
+    }
+    // Create our default CTFontRef
+    mCTFont[0] =
+        CreateCTFontWithFeatures(aFont->GetAdjustedSize(),
+                                 GetFeaturesDescriptor(kDefaultFeatures));
 }
 
 gfxCoreTextShaper::~gfxCoreTextShaper()
 {
     if (mAttributesDictLTR) {
         ::CFRelease(mAttributesDictLTR);
     }
     if (mAttributesDictRTL) {
         ::CFRelease(mAttributesDictRTL);
     }
-    if (mCTFont) {
-        ::CFRelease(mCTFont);
+    for (size_t i = 0; i < kMaxFontInstances; i++) {
+        if (mCTFont[i]) {
+            ::CFRelease(mCTFont[i]);
+        }
     }
 }
 
 static bool
 IsBuggyIndicScript(unicode::Script aScript)
 {
     return aScript == unicode::Script::BENGALI ||
            aScript == unicode::Script::KANNADA ||
@@ -130,54 +131,48 @@ gfxCoreTextShaper::ShapeText(DrawTarget 
     // current direction, creating it if necessary.
     CFDictionaryRef attrObj =
         isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR;
     if (!attrObj) {
         attrObj = CreateAttrDict(isRightToLeft);
         (isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR) = attrObj;
     }
 
-    CTFontRef tempCTFont = nullptr;
+    FeatureFlags featureFlags = kDefaultFeatures;
     if (IsBuggyIndicScript(aScript)) {
         // To work around buggy Indic AAT fonts shipped with OS X,
         // we re-enable the Line Initial Smart Swashes feature that is needed
         // for "split vowels" to work in at least Bengali and Kannada fonts.
         // Affected fonts include Bangla MN, Bangla Sangam MN, Kannada MN,
         // Kannada Sangam MN. See bugs 686225, 728557, 953231, 1145515.
         // Also applies to Oriya and Khmer, see bug 1370927 and bug 1403166.
-        tempCTFont =
-            CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
-                                     aShapedText->DisableLigatures()
-                                         ? GetIndicDisableLigaturesDescriptor()
-                                         : GetIndicFeaturesDescriptor());
-    } else if (aShapedText->DisableLigatures()) {
+        featureFlags |= kIndicFeatures;
+    }
+    if (aShapedText->DisableLigatures()) {
         // For letterspacing (or maybe other situations) we need to make
         // a copy of the CTFont with the ligature feature disabled.
-        tempCTFont =
-            CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
-                                     addSmallCaps
-                                         ? GetSmallCapDisableLigDescriptor()
-                                         : GetDisableLigaturesDescriptor());
-    } else if (addSmallCaps) {
-        tempCTFont =
-            CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
-                                     GetSmallCapsDescriptor());
+        featureFlags |= kDisableLigatures;
+    }
+    if (addSmallCaps) {
+        featureFlags |= kAddSmallCaps;
     }
 
     // For the disabled-ligature, buggy-indic-font or small-caps case, replace
-    // the standard CTFont in the attribute dictionary with a tweaked version.
+    // the default CTFont in the attribute dictionary with a tweaked version.
     CFMutableDictionaryRef mutableAttr = nullptr;
-    if (tempCTFont) {
-        mutableAttr = ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2,
-                                                      attrObj);
+    if (featureFlags != 0) {
+        if (!mCTFont[featureFlags]) {
+            mCTFont[featureFlags] =
+                CreateCTFontWithFeatures(mFont->GetAdjustedSize(),
+                                         GetFeaturesDescriptor(featureFlags));
+        }
+        mutableAttr =
+            ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, attrObj);
         ::CFDictionaryReplaceValue(mutableAttr,
-                                   kCTFontAttributeName, tempCTFont);
-        // Having created the dict, we're finished with our temporary
-        // Indic and/or ligature-disabled or small-caps CTFontRef.
-        ::CFRelease(tempCTFont);
+                                   kCTFontAttributeName, mCTFont[featureFlags]);
         attrObj = mutableAttr;
     }
 
     // Now we can create an attributed string
     CFAttributedStringRef attrStringObj =
         ::CFAttributedStringCreate(kCFAllocatorDefault, stringObj, attrObj);
     ::CFRelease(stringObj);
 
@@ -572,17 +567,17 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxS
 
 // We also cache feature descriptors for shaping with disabled ligatures, and
 // for buggy Indic AAT font workarounds, created on an as-needed basis.
 
 #define MAX_FEATURES  5 // max used by any of our Get*Descriptor functions
 
 CTFontDescriptorRef
 gfxCoreTextShaper::CreateFontFeaturesDescriptor(
-    const std::pair<SInt16,SInt16> aFeatures[],
+    const std::pair<SInt16,SInt16>* aFeatures,
     size_t aCount)
 {
     MOZ_ASSERT(aCount <= MAX_FEATURES);
 
     CFDictionaryRef featureSettings[MAX_FEATURES];
 
     for (size_t i = 0; i < aCount; i++) {
         CFNumberRef type = ::CFNumberCreate(kCFAllocatorDefault,
@@ -632,143 +627,57 @@ gfxCoreTextShaper::CreateFontFeaturesDes
     CTFontDescriptorRef descriptor =
         ::CTFontDescriptorCreateWithAttributes(attributesDict);
     ::CFRelease(attributesDict);
 
     return descriptor;
 }
 
 CTFontDescriptorRef
-gfxCoreTextShaper::GetDefaultFeaturesDescriptor()
-{
-    if (sDefaultFeaturesDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kDefaultFeatures[] = {
-            { kSmartSwashType, kLineInitialSwashesOffSelector },
-            { kSmartSwashType, kLineFinalSwashesOffSelector }
-        };
-        static_assert(ArrayLength(kDefaultFeatures) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sDefaultFeaturesDescriptor =
-            CreateFontFeaturesDescriptor(kDefaultFeatures,
-                                         ArrayLength(kDefaultFeatures));
-    }
-    return sDefaultFeaturesDescriptor;
-}
-
-CTFontDescriptorRef
-gfxCoreTextShaper::GetSmallCapsDescriptor()
+gfxCoreTextShaper::GetFeaturesDescriptor(FeatureFlags aFeatureFlags)
 {
-    if (sSmallCapsDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kSmallCaps[] = {
-            { kSmartSwashType, kLineInitialSwashesOffSelector },
-            { kSmartSwashType, kLineFinalSwashesOffSelector },
-            { kLetterCaseType, kSmallCapsSelector },
-            { kLowerCaseType, kLowerCaseSmallCapsSelector }
-        };
-        static_assert(ArrayLength(kSmallCaps) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sSmallCapsDescriptor =
-            CreateFontFeaturesDescriptor(kSmallCaps,
-                                         ArrayLength(kSmallCaps));
-    }
-    return sSmallCapsDescriptor;
-}
-
-CTFontDescriptorRef
-gfxCoreTextShaper::GetDisableLigaturesDescriptor()
-{
-    if (sDisableLigaturesDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kDisableLigatures[] = {
-            { kSmartSwashType, kLineInitialSwashesOffSelector },
-            { kSmartSwashType, kLineFinalSwashesOffSelector },
-            { kLigaturesType, kCommonLigaturesOffSelector }
-        };
-        static_assert(ArrayLength(kDisableLigatures) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sDisableLigaturesDescriptor =
-            CreateFontFeaturesDescriptor(kDisableLigatures,
-                                         ArrayLength(kDisableLigatures));
+    MOZ_ASSERT(aFeatureFlags < kMaxFontInstances);
+    if (!sFeaturesDescriptor[aFeatureFlags]) {
+        typedef std::pair<SInt16,SInt16> FeatT;
+        AutoTArray<FeatT,MAX_FEATURES> features;
+        features.AppendElement(FeatT(kSmartSwashType,
+                                     kLineFinalSwashesOffSelector));
+        if ((aFeatureFlags & kIndicFeatures) == 0) {
+            features.AppendElement(FeatT(kSmartSwashType,
+                                         kLineInitialSwashesOffSelector));
+        }
+        if (aFeatureFlags & kAddSmallCaps) {
+            features.AppendElement(FeatT(kLetterCaseType,
+                                         kSmallCapsSelector));
+            features.AppendElement(FeatT(kLowerCaseType,
+                                         kLowerCaseSmallCapsSelector));
+        }
+        if (aFeatureFlags & kDisableLigatures) {
+            features.AppendElement(FeatT(kLigaturesType,
+                                         kCommonLigaturesOffSelector));
+        }
+        MOZ_ASSERT(features.Length() <= MAX_FEATURES);
+        sFeaturesDescriptor[aFeatureFlags] =
+            CreateFontFeaturesDescriptor(features.Elements(),
+                                         features.Length());
     }
-    return sDisableLigaturesDescriptor;
-}
-
-CTFontDescriptorRef
-gfxCoreTextShaper::GetSmallCapDisableLigDescriptor()
-{
-    if (sSmallCapDisableLigDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kFeatures[] = {
-            { kSmartSwashType, kLineInitialSwashesOffSelector },
-            { kSmartSwashType, kLineFinalSwashesOffSelector },
-            { kLigaturesType, kCommonLigaturesOffSelector },
-            { kLetterCaseType, kSmallCapsSelector },
-            { kLowerCaseType, kLowerCaseSmallCapsSelector }
-        };
-        static_assert(ArrayLength(kFeatures) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sSmallCapDisableLigDescriptor =
-            CreateFontFeaturesDescriptor(kFeatures,
-                                         ArrayLength(kFeatures));
-    }
-    return sSmallCapDisableLigDescriptor;
-}
-
-CTFontDescriptorRef
-gfxCoreTextShaper::GetIndicFeaturesDescriptor()
-{
-    if (sIndicFeaturesDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kIndicFeatures[] = {
-            { kSmartSwashType, kLineFinalSwashesOffSelector }
-        };
-        static_assert(ArrayLength(kIndicFeatures) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sIndicFeaturesDescriptor =
-            CreateFontFeaturesDescriptor(kIndicFeatures,
-                                         ArrayLength(kIndicFeatures));
-    }
-    return sIndicFeaturesDescriptor;
-}
-
-CTFontDescriptorRef
-gfxCoreTextShaper::GetIndicDisableLigaturesDescriptor()
-{
-    if (sIndicDisableLigaturesDescriptor == nullptr) {
-        const std::pair<SInt16,SInt16> kIndicDisableLigatures[] = {
-            { kSmartSwashType, kLineFinalSwashesOffSelector },
-            { kLigaturesType, kCommonLigaturesOffSelector }
-        };
-        static_assert(ArrayLength(kIndicDisableLigatures) <= MAX_FEATURES,
-                      "need to increase MAX_FEATURES");
-        sIndicDisableLigaturesDescriptor =
-            CreateFontFeaturesDescriptor(kIndicDisableLigatures,
-                                         ArrayLength(kIndicDisableLigatures));
-    }
-    return sIndicDisableLigaturesDescriptor;
+    return sFeaturesDescriptor[aFeatureFlags];
 }
 
 CTFontRef
 gfxCoreTextShaper::CreateCTFontWithFeatures(CGFloat aSize,
                                             CTFontDescriptorRef aDescriptor)
 {
     CGFontRef cgFont = static_cast<gfxMacFont*>(mFont)->GetCGFontRef();
     return gfxMacFont::CreateCTFontFromCGFontWithVariations(cgFont, aSize,
                                                             aDescriptor);
 }
 
 void
 gfxCoreTextShaper::Shutdown() // [static]
 {
-    if (sIndicDisableLigaturesDescriptor != nullptr) {
-        ::CFRelease(sIndicDisableLigaturesDescriptor);
-        sIndicDisableLigaturesDescriptor = nullptr;
-    }
-    if (sIndicFeaturesDescriptor != nullptr) {
-        ::CFRelease(sIndicFeaturesDescriptor);
-        sIndicFeaturesDescriptor = nullptr;
-    }
-    if (sDisableLigaturesDescriptor != nullptr) {
-        ::CFRelease(sDisableLigaturesDescriptor);
-        sDisableLigaturesDescriptor = nullptr;
-    }
-    if (sDefaultFeaturesDescriptor != nullptr) {
-        ::CFRelease(sDefaultFeaturesDescriptor);
-        sDefaultFeaturesDescriptor = nullptr;
+    for (size_t i = 0; i < kMaxFontInstances; i++) {
+        if (sFeaturesDescriptor[i] != nullptr) {
+            ::CFRelease(sFeaturesDescriptor[i]);
+            sFeaturesDescriptor[i] = nullptr;
+        }
     }
 }
--- a/gfx/thebes/gfxCoreTextShaper.h
+++ b/gfx/thebes/gfxCoreTextShaper.h
@@ -25,18 +25,33 @@ public:
                    Script           aScript,
                    bool             aVertical,
                    RoundingFlags    aRounding,
                    gfxShapedText   *aShapedText) override;
 
     // clean up static objects that may have been cached
     static void Shutdown();
 
+    // Flags used to track what AAT features should be enabled on the Core Text
+    // font instance. (Internal; only public so that we can use the
+    // MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS macro below.)
+    enum FeatureFlags : uint8_t {
+        kDefaultFeatures  = 0x00,
+        // bit flags for non-default feature settings we might need
+        // to use, which will require separate font instances
+        kDisableLigatures = 0x01,
+        kAddSmallCaps     = 0x02,
+        kIndicFeatures    = 0x04,
+
+        // number of font instances, indexed by OR-ing the flags above
+        kMaxFontInstances = 8
+    };
+
 protected:
-    CTFontRef mCTFont;
+    CTFontRef mCTFont[kMaxFontInstances];
 
     // attributes for shaping text with LTR or RTL directionality
     CFDictionaryRef mAttributesDictLTR;
     CFDictionaryRef mAttributesDictRTL;
 
     nsresult SetGlyphsFromRun(gfxShapedText *aShapedText,
                               uint32_t       aOffset,
                               uint32_t       aLength,
@@ -44,32 +59,20 @@ protected:
 
     CTFontRef CreateCTFontWithFeatures(CGFloat aSize,
                                        CTFontDescriptorRef aDescriptor);
 
     CFDictionaryRef CreateAttrDict(bool aRightToLeft);
     CFDictionaryRef CreateAttrDictWithoutDirection();
 
     static CTFontDescriptorRef
-    CreateFontFeaturesDescriptor(const std::pair<SInt16,SInt16> aFeatures[],
+    CreateFontFeaturesDescriptor(const std::pair<SInt16,SInt16>* aFeatures,
                                  size_t aCount);
 
-    static CTFontDescriptorRef GetDefaultFeaturesDescriptor();
-    static CTFontDescriptorRef GetSmallCapsDescriptor();
-    static CTFontDescriptorRef GetDisableLigaturesDescriptor();
-    static CTFontDescriptorRef GetSmallCapDisableLigDescriptor();
-    static CTFontDescriptorRef GetIndicFeaturesDescriptor();
-    static CTFontDescriptorRef GetIndicDisableLigaturesDescriptor();
+    static CTFontDescriptorRef GetFeaturesDescriptor(FeatureFlags aFeatureFlags);
 
-    // cached font descriptor, created the first time it's needed
-    static CTFontDescriptorRef    sDefaultFeaturesDescriptor;
-    static CTFontDescriptorRef    sSmallCapsDescriptor;
-
-    // cached descriptor for adding disable-ligatures setting to a font
-    static CTFontDescriptorRef    sDisableLigaturesDescriptor;
-    static CTFontDescriptorRef    sSmallCapDisableLigDescriptor;
-
-    // feature descriptors for buggy Indic AAT font workaround
-    static CTFontDescriptorRef    sIndicFeaturesDescriptor;
-    static CTFontDescriptorRef    sIndicDisableLigaturesDescriptor;
+    // cached font descriptors, created the first time they're needed
+    static CTFontDescriptorRef sFeaturesDescriptor[kMaxFontInstances];
 };
 
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxCoreTextShaper::FeatureFlags)
+
 #endif /* GFX_CORETEXTSHAPER_H */
--- a/ipc/chromium/src/base/pickle.h
+++ b/ipc/chromium/src/base/pickle.h
@@ -16,17 +16,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/BufferList.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/TimeStamp.h"
 #ifdef FUZZING
 #include "base/singleton.h"
 #include "mozilla/ipc/Faulty.h"
 #endif
-#if (!defined(RELEASE_OR_BETA) && !defined(FUZZING)) || defined(DEBUG)
+#if !defined(FUZZING) && (!defined(RELEASE_OR_BETA) || defined(DEBUG))
 #define MOZ_PICKLE_SENTINEL_CHECKING
 #endif
 class Pickle;
 class PickleIterator {
 public:
   explicit PickleIterator(const Pickle& pickle);
 
 private:
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -10,17 +10,27 @@
 #include <algorithm>
 #include <stdint.h>
 
 #include "jstypes.h"
 
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
-class JSTracer;
+#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
+#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
+
+class JS_PUBLIC_API(JSTracer);
+
+#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
+#pragma GCC diagnostic pop
+#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
+
 class PseudoStack;
 
 // This file defines the classes PseudoStack and ProfileEntry.
 // The PseudoStack manages an array of ProfileEntries.
 // Usage:
 //
 //  PseudoStack* pseudoStack = ...;
 //
--- a/js/public/TypeDecls.h
+++ b/js/public/TypeDecls.h
@@ -36,17 +36,17 @@ struct JSFreeOp;
 
 struct jsid;
 
 namespace JS {
 
 typedef unsigned char Latin1Char;
 
 class Symbol;
-class Value;
+union Value;
 class Realm;
 struct Runtime;
 struct Zone;
 
 template <typename T> class Handle;
 template <typename T> class MutableHandle;
 template <typename T> class Rooted;
 template <typename T> class PersistentRooted;
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -20,17 +20,17 @@
 
 #include "js-config.h"
 #include "jstypes.h"
 
 #include "js/GCAPI.h"
 #include "js/RootingAPI.h"
 #include "js/Utility.h"
 
-namespace JS { class Value; }
+namespace JS { union Value; }
 
 /* JS::Value can store a full int32_t. */
 #define JSVAL_INT_BITS          32
 #define JSVAL_INT_MIN           ((int32_t)0x80000000)
 #define JSVAL_INT_MAX           ((int32_t)0x7fffffff)
 
 #if defined(JS_PUNBOX64)
 # define JSVAL_TAG_SHIFT 47
@@ -311,84 +311,182 @@ CanonicalizeNaN(double d)
  *   that toString, toObject, toSymbol will return an invalid pointer (because
  *   some high bits will be set) when called on a Value with a different type
  *   tag.
  *
  * - On 32-bit platforms,when unboxing an object/string/symbol Value, we use a
  *   conditional move (not speculated) to zero the payload register if the type
  *   doesn't match.
  */
-class MOZ_NON_PARAM alignas(8) Value
+union MOZ_NON_PARAM alignas(8) Value
 {
+#if !defined(_MSC_VER) && !defined(__sparc)
+  // Don't expose Value's fields unless we have to: MSVC (bug 689101) and SPARC
+  // (bug 737344) require Value be POD to pass it by value and not in memory.
+  // More precisely, we don't want Value return values compiled as outparams.
+  private:
+#endif
+
+    uint64_t asBits_;
+    double asDouble_;
+
+#if defined(JS_PUNBOX64) && !defined(_WIN64)
+    // MSVC doesn't pack these correctly :-(
+    struct {
+#  if MOZ_LITTLE_ENDIAN
+        uint64_t payload47_ : 47;
+        JSValueTag tag_ : 17;
+#  else
+        JSValueTag tag_ : 17;
+        uint64_t payload47_ : 47;
+#  endif // MOZ_LITTLE_ENDIAN
+    } debugView_;
+#endif // defined(JS_PUNBOX64) && !defined(_WIN64)
+
+    struct {
+#if defined(JS_PUNBOX64)
+#  if MOZ_BIG_ENDIAN
+        uint32_t : 32; // padding
+#  endif // MOZ_BIG_ENDIAN
+        union {
+            int32_t i32_;
+            uint32_t u32_;
+            JSWhyMagic why_;
+        } payload_;
+#elif defined(JS_NUNBOX32)
+#  if MOZ_BIG_ENDIAN
+        JSValueTag tag_;
+#  endif // MOZ_BIG_ENDIAN
+        union {
+            int32_t i32_;
+            uint32_t u32_;
+            uint32_t  boo_;     // Don't use |bool| -- it must be four bytes.
+            JSString* str_;
+            JS::Symbol* sym_;
+            JSObject* obj_;
+            js::gc::Cell* cell_;
+            void* ptr_;
+            JSWhyMagic why_;
+        } payload_;
+#  if MOZ_LITTLE_ENDIAN
+        JSValueTag tag_;
+#  endif // MOZ_LITTLE_ENDIAN
+#endif // defined(JS_PUNBOX64)
+    } s_;
+
+  public:
+    // The default constructor leaves Value uninitialized. Adding a default
+    // constructor prevents Value from being stored in a union.
+    Value() = default;
+    Value(const Value& v) = default;
+
+  private:
+    explicit constexpr Value(uint64_t asBits) : asBits_(asBits) {}
+    explicit constexpr Value(double d) : asDouble_(d) {}
+
+    static_assert(sizeof(JSValueType) == 1,
+                  "type bits must fit in a single byte");
+    static_assert(sizeof(JSValueTag) == 4,
+                  "32-bit Value's tag_ must have size 4 to complement the "
+                  "payload union's size 4");
+    static_assert(sizeof(JSWhyMagic) <= 4,
+                  "32-bit Value's JSWhyMagic payload field must not inflate "
+                  "the payload beyond 4 bytes");
+
   public:
 #if defined(JS_NUNBOX32)
     using PayloadType = uint32_t;
 #elif defined(JS_PUNBOX64)
     using PayloadType = uint64_t;
 #endif
 
-    /*
-     * N.B. the default constructor leaves Value unitialized. Adding a default
-     * constructor prevents Value from being stored in a union.
-     */
-    Value() = default;
-    Value(const Value& v) = default;
+    static constexpr uint64_t
+    bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
+    {
+#if defined(JS_NUNBOX32)
+        return (uint64_t(uint32_t(tag)) << 32) | payload;
+#elif defined(JS_PUNBOX64)
+        return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
+#endif
+    }
+
+    static constexpr Value
+    fromTagAndPayload(JSValueTag tag, PayloadType payload)
+    {
+        return fromRawBits(bitsFromTagAndPayload(tag, payload));
+    }
 
+    static constexpr Value
+    fromRawBits(uint64_t asBits) {
+        return Value(asBits);
+    }
+
+    static constexpr Value
+    fromInt32(int32_t i) {
+        return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
+    }
+
+    static constexpr Value
+    fromDouble(double d) {
+        return Value(d);
+    }
+
+  public:
     /**
      * Returns false if creating a NumberValue containing the given type would
      * be lossy, true otherwise.
      */
     template <typename T>
     static bool isNumberRepresentable(const T t) {
         return T(double(t)) == t;
     }
 
     /*** Mutators ***/
 
     void setNull() {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
     }
 
     void setUndefined() {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
     }
 
     void setInt32(int32_t i) {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
     }
 
     int32_t& getInt32Ref() {
         MOZ_ASSERT(isInt32());
-        return data.s.payload.i32;
+        return s_.payload_.i32_;
     }
 
     void setDouble(double d) {
-        // Don't assign to data.asDouble to fix a miscompilation with
-        // GCC 5.2.1 and 5.3.1. See bug 1312488.
-        data = layout(d);
+        // Don't assign to asDouble_ to fix a miscompilation with GCC 5.2.1 and
+        // 5.3.1. See bug 1312488.
+        *this = Value(d);
         MOZ_ASSERT(isDouble());
     }
 
     void setNaN() {
         setDouble(GenericNaN());
     }
 
     double& getDoubleRef() {
         MOZ_ASSERT(isDouble());
-        return data.asDouble;
+        return asDouble_;
     }
 
     void setString(JSString* str) {
         MOZ_ASSERT(js::gc::IsCellPointerValid(str));
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
     }
 
     void setSymbol(JS::Symbol* sym) {
         MOZ_ASSERT(js::gc::IsCellPointerValid(sym));
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
     }
 
     void setObject(JSObject& obj) {
         MOZ_ASSERT(js::gc::IsCellPointerValid(&obj));
 
         // This should not be possible and is undefined behavior, but some
         // ObjectValue(nullptr) are sneaking in. Try to catch them here, if
         // indeed they are going through this code. I tested gcc, and it at
@@ -408,32 +506,32 @@ class MOZ_NON_PARAM alignas(8) Value
         // It throws syntax error.
         MOZ_ASSERT((((uintptr_t)&obj) >> JSVAL_TAG_SHIFT) == 0);
 #endif
         setObjectNoCheck(&obj);
     }
 
   private:
     void setObjectNoCheck(JSObject* obj) {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
     }
 
     friend inline Value js::PoisonedObjectValue(uintptr_t poison);
 
   public:
     void setBoolean(bool b) {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
     }
 
     void setMagic(JSWhyMagic why) {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
     }
 
     void setMagicUint32(uint32_t payload) {
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
     }
 
     bool setNumber(uint32_t ui) {
         if (ui > JSVAL_INT_MAX) {
             setDouble((double)ui);
             return false;
         } else {
             setInt32((int32_t)ui);
@@ -455,156 +553,156 @@ class MOZ_NON_PARAM alignas(8) Value
     void setObjectOrNull(JSObject* arg) {
         if (arg)
             setObject(*arg);
         else
             setNull();
     }
 
     void swap(Value& rhs) {
-        uint64_t tmp = rhs.data.asBits;
-        rhs.data.asBits = data.asBits;
-        data.asBits = tmp;
+        uint64_t tmp = rhs.asBits_;
+        rhs.asBits_ = asBits_;
+        asBits_ = tmp;
     }
 
   private:
     JSValueTag toTag() const {
 #if defined(JS_NUNBOX32)
-        return data.s.tag;
+        return s_.tag_;
 #elif defined(JS_PUNBOX64)
-        return JSValueTag(data.asBits >> JSVAL_TAG_SHIFT);
+        return JSValueTag(asBits_ >> JSVAL_TAG_SHIFT);
 #endif
     }
 
   public:
     /*** JIT-only interfaces to interact with and create raw Values ***/
 #if defined(JS_NUNBOX32)
     PayloadType toNunboxPayload() const {
-        return static_cast<PayloadType>(data.s.payload.i32);
+        return static_cast<PayloadType>(s_.payload_.i32_);
     }
 
     JSValueTag toNunboxTag() const {
-        return data.s.tag;
+        return s_.tag_;
     }
 #elif defined(JS_PUNBOX64)
     const void* bitsAsPunboxPointer() const {
-        return reinterpret_cast<void*>(data.asBits);
+        return reinterpret_cast<void*>(asBits_);
     }
 #endif
 
     /*** Value type queries ***/
 
     /*
      * N.B. GCC, in some but not all cases, chooses to emit signed comparison
      * of JSValueTag even though its underlying type has been forced to be
      * uint32_t.  Thus, all comparisons should explicitly cast operands to
      * uint32_t.
      */
 
     bool isUndefined() const {
 #if defined(JS_NUNBOX32)
         return toTag() == JSVAL_TAG_UNDEFINED;
 #elif defined(JS_PUNBOX64)
-        return data.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
+        return asBits_ == JSVAL_SHIFTED_TAG_UNDEFINED;
 #endif
     }
 
     bool isNull() const {
 #if defined(JS_NUNBOX32)
         return toTag() == JSVAL_TAG_NULL;
 #elif defined(JS_PUNBOX64)
-        return data.asBits == JSVAL_SHIFTED_TAG_NULL;
+        return asBits_ == JSVAL_SHIFTED_TAG_NULL;
 #endif
     }
 
     bool isNullOrUndefined() const {
         return isNull() || isUndefined();
     }
 
     bool isInt32() const {
         return toTag() == JSVAL_TAG_INT32;
     }
 
     bool isInt32(int32_t i32) const {
-        return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
+        return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
     }
 
     bool isDouble() const {
 #if defined(JS_NUNBOX32)
         return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
 #elif defined(JS_PUNBOX64)
-        return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
+        return (asBits_ | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
 #endif
     }
 
     bool isNumber() const {
 #if defined(JS_NUNBOX32)
         MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR);
         return uint32_t(toTag()) <= uint32_t(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET);
 #elif defined(JS_PUNBOX64)
-        return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
+        return asBits_ < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
 #endif
     }
 
     bool isString() const {
         return toTag() == JSVAL_TAG_STRING;
     }
 
     bool isSymbol() const {
         return toTag() == JSVAL_TAG_SYMBOL;
     }
 
     bool isObject() const {
 #if defined(JS_NUNBOX32)
         return toTag() == JSVAL_TAG_OBJECT;
 #elif defined(JS_PUNBOX64)
-        MOZ_ASSERT((data.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
-        return data.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
+        MOZ_ASSERT((asBits_ >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
+        return asBits_ >= JSVAL_SHIFTED_TAG_OBJECT;
 #endif
     }
 
     bool isPrimitive() const {
 #if defined(JS_NUNBOX32)
         return uint32_t(toTag()) < uint32_t(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET);
 #elif defined(JS_PUNBOX64)
-        return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
+        return asBits_ < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
 #endif
     }
 
     bool isObjectOrNull() const {
         return isObject() || isNull();
     }
 
     bool isGCThing() const {
 #if defined(JS_NUNBOX32)
         /* gcc sometimes generates signed < without explicit casts. */
         return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET);
 #elif defined(JS_PUNBOX64)
-        return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
+        return asBits_ >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
 #endif
     }
 
     bool isBoolean() const {
         return toTag() == JSVAL_TAG_BOOLEAN;
     }
 
     bool isTrue() const {
-        return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
+        return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
     }
 
     bool isFalse() const {
-        return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
+        return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
     }
 
     bool isMagic() const {
         return toTag() == JSVAL_TAG_MAGIC;
     }
 
     bool isMagic(JSWhyMagic why) const {
-        MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
+        MOZ_ASSERT_IF(isMagic(), s_.payload_.why_ == why);
         return isMagic();
     }
 
     JS::TraceKind traceKind() const {
         MOZ_ASSERT(isGCThing());
         static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
                       "Value type tags must correspond with JS::TraceKinds.");
         static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
@@ -613,131 +711,131 @@ class MOZ_NON_PARAM alignas(8) Value
                       "Value type tags must correspond with JS::TraceKinds.");
         if (MOZ_UNLIKELY(isPrivateGCThing()))
             return JS::GCThingTraceKind(toGCThing());
         return JS::TraceKind(toTag() & 0x03);
     }
 
     JSWhyMagic whyMagic() const {
         MOZ_ASSERT(isMagic());
-        return data.s.payload.why;
+        return s_.payload_.why_;
     }
 
     uint32_t magicUint32() const {
         MOZ_ASSERT(isMagic());
-        return data.s.payload.u32;
+        return s_.payload_.u32_;
     }
 
     /*** Comparison ***/
 
     bool operator==(const Value& rhs) const {
-        return data.asBits == rhs.data.asBits;
+        return asBits_ == rhs.asBits_;
     }
 
     bool operator!=(const Value& rhs) const {
-        return data.asBits != rhs.data.asBits;
+        return asBits_ != rhs.asBits_;
     }
 
     friend inline bool SameType(const Value& lhs, const Value& rhs);
 
     /*** Extract the value's typed payload ***/
 
     int32_t toInt32() const {
         MOZ_ASSERT(isInt32());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.i32;
+        return s_.payload_.i32_;
 #elif defined(JS_PUNBOX64)
-        return int32_t(data.asBits);
+        return int32_t(asBits_);
 #endif
     }
 
     double toDouble() const {
         MOZ_ASSERT(isDouble());
-        return data.asDouble;
+        return asDouble_;
     }
 
     double toNumber() const {
         MOZ_ASSERT(isNumber());
         return isDouble() ? toDouble() : double(toInt32());
     }
 
     JSString* toString() const {
         MOZ_ASSERT(isString());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.str;
+        return s_.payload_.str_;
 #elif defined(JS_PUNBOX64)
-        return reinterpret_cast<JSString*>(data.asBits ^ JSVAL_SHIFTED_TAG_STRING);
+        return reinterpret_cast<JSString*>(asBits_ ^ JSVAL_SHIFTED_TAG_STRING);
 #endif
     }
 
     JS::Symbol* toSymbol() const {
         MOZ_ASSERT(isSymbol());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.sym;
+        return s_.payload_.sym_;
 #elif defined(JS_PUNBOX64)
-        return reinterpret_cast<JS::Symbol*>(data.asBits ^ JSVAL_SHIFTED_TAG_SYMBOL);
+        return reinterpret_cast<JS::Symbol*>(asBits_ ^ JSVAL_SHIFTED_TAG_SYMBOL);
 #endif
     }
 
     JSObject& toObject() const {
         MOZ_ASSERT(isObject());
 #if defined(JS_NUNBOX32)
-        return *data.s.payload.obj;
+        return *s_.payload_.obj_;
 #elif defined(JS_PUNBOX64)
-        uint64_t ptrBits = data.asBits ^ JSVAL_SHIFTED_TAG_OBJECT;
+        uint64_t ptrBits = asBits_ ^ JSVAL_SHIFTED_TAG_OBJECT;
         MOZ_ASSERT(ptrBits);
         MOZ_ASSERT((ptrBits & 0x7) == 0);
         return *reinterpret_cast<JSObject*>(ptrBits);
 #endif
     }
 
     JSObject* toObjectOrNull() const {
         MOZ_ASSERT(isObjectOrNull());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.obj;
+        return s_.payload_.obj_;
 #elif defined(JS_PUNBOX64)
         // Note: the 'Spectre mitigations' comment at the top of this class
         // explains why we use XOR here and in other to* methods.
-        uint64_t ptrBits = (data.asBits ^ JSVAL_SHIFTED_TAG_OBJECT) & ~JSVAL_OBJECT_OR_NULL_BIT;
+        uint64_t ptrBits = (asBits_ ^ JSVAL_SHIFTED_TAG_OBJECT) & ~JSVAL_OBJECT_OR_NULL_BIT;
         MOZ_ASSERT((ptrBits & 0x7) == 0);
         return reinterpret_cast<JSObject*>(ptrBits);
 #endif
     }
 
     js::gc::Cell* toGCThing() const {
         MOZ_ASSERT(isGCThing());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.cell;
+        return s_.payload_.cell_;
 #elif defined(JS_PUNBOX64)
-        uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK_GCTHING;
+        uint64_t ptrBits = asBits_ & JSVAL_PAYLOAD_MASK_GCTHING;
         MOZ_ASSERT((ptrBits & 0x7) == 0);
         return reinterpret_cast<js::gc::Cell*>(ptrBits);
 #endif
     }
 
     GCCellPtr toGCCellPtr() const {
         return GCCellPtr(toGCThing(), traceKind());
     }
 
     bool toBoolean() const {
         MOZ_ASSERT(isBoolean());
 #if defined(JS_NUNBOX32)
-        return bool(data.s.payload.boo);
+        return bool(s_.payload_.boo_);
 #elif defined(JS_PUNBOX64)
-        return bool(int32_t(data.asBits));
+        return bool(int32_t(asBits_));
 #endif
     }
 
     uint32_t payloadAsRawUint32() const {
         MOZ_ASSERT(!isDouble());
-        return data.s.payload.u32;
+        return s_.payload_.u32_;
     }
 
     uint64_t asRawBits() const {
-        return data.asBits;
+        return asBits_;
     }
 
     JSValueType extractNonDoubleType() const {
         uint32_t type = toTag() & 0xF;
         MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
         return JSValueType(type);
     }
 
@@ -748,31 +846,31 @@ class MOZ_NON_PARAM alignas(8) Value
      * that fit in the 64-bit payload. It is the caller's responsibility, after
      * storing to a value with setPrivateX to read only using getPrivateX.
      * Privates values are given a type which ensures they are not marked.
      */
 
     void setPrivate(void* ptr) {
         MOZ_ASSERT((uintptr_t(ptr) & 1) == 0);
 #if defined(JS_NUNBOX32)
-        data.s.tag = JSValueTag(0);
-        data.s.payload.ptr = ptr;
+        s_.tag_ = JSValueTag(0);
+        s_.payload_.ptr_ = ptr;
 #elif defined(JS_PUNBOX64)
-        data.asBits = uintptr_t(ptr) >> 1;
+        asBits_ = uintptr_t(ptr) >> 1;
 #endif
         MOZ_ASSERT(isDouble());
     }
 
     void* toPrivate() const {
         MOZ_ASSERT(isDouble());
 #if defined(JS_NUNBOX32)
-        return data.s.payload.ptr;
+        return s_.payload_.ptr_;
 #elif defined(JS_PUNBOX64)
-        MOZ_ASSERT((data.asBits & 0x8000000000000000ULL) == 0);
-        return reinterpret_cast<void*>(data.asBits << 1);
+        MOZ_ASSERT((asBits_ & 0x8000000000000000ULL) == 0);
+        return reinterpret_cast<void*>(asBits_ << 1);
 #endif
     }
 
     void setPrivateUint32(uint32_t ui) {
         MOZ_ASSERT(uint32_t(int32_t(ui)) == ui);
         setInt32(int32_t(ui));
     }
 
@@ -800,140 +898,22 @@ class MOZ_NON_PARAM alignas(8) Value
         MOZ_ASSERT(js::gc::IsCellPointerValid(cell));
 #if defined(JS_PUNBOX64)
         // VisualStudio cannot contain parenthesized C++ style cast and shift
         // inside decltype in template parameter:
         //   AssertionConditionType<decltype((uintptr_t(x) >> 1))>
         // It throws syntax error.
         MOZ_ASSERT((((uintptr_t)cell) >> JSVAL_TAG_SHIFT) == 0);
 #endif
-        data.asBits = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
+        asBits_ = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
     }
 
     bool isPrivateGCThing() const {
         return toTag() == JSVAL_TAG_PRIVATE_GCTHING;
     }
-
-    const uintptr_t* payloadUIntPtr() const {
-#if defined(JS_NUNBOX32)
-        return &data.s.payload.uintptr;
-#elif defined(JS_PUNBOX64)
-        return &data.asUIntPtr;
-#endif
-    }
-
-#if !defined(_MSC_VER) && !defined(__sparc)
-  // Value must be POD so that MSVC will pass it by value and not in memory
-  // (bug 689101); the same is true for SPARC as well (bug 737344).  More
-  // precisely, we don't want Value return values compiled as out params.
-  private:
-#endif
-
-    union layout {
-        uint64_t asBits;
-        double asDouble;
-        void* asPtr;
-#if defined(JS_PUNBOX64)
-        uintptr_t asUIntPtr;
-#endif // defined(JS_PUNBOX64)
-
-#if defined(JS_PUNBOX64) && !defined(_WIN64)
-        /* MSVC does not pack these correctly :-( */
-        struct {
-#  if MOZ_LITTLE_ENDIAN
-            uint64_t   payload47 : 47;
-            JSValueTag tag : 17;
-#  else
-            JSValueTag tag : 17;
-            uint64_t   payload47 : 47;
-#  endif // MOZ_LITTLE_ENDIAN
-        } debugView;
-#endif // defined(JS_PUNBOX64) && !defined(_WIN64)
-
-        struct {
-#if defined(JS_PUNBOX64)
-#  if MOZ_BIG_ENDIAN
-            uint32_t padding;
-#  endif // MOZ_BIG_ENDIAN
-            union {
-                int32_t    i32;
-                uint32_t   u32;
-                JSWhyMagic why;
-            } payload;
-#else
-#  if MOZ_BIG_ENDIAN
-            JSValueTag tag;
-#  endif // MOZ_BIG_ENDIAN
-            union {
-                int32_t        i32;
-                uint32_t       u32;
-                uint32_t       boo;     // Don't use |bool| -- it must be four bytes.
-                JSString*      str;
-                JS::Symbol*    sym;
-                JSObject*      obj;
-                js::gc::Cell*  cell;
-                void*          ptr;
-                JSWhyMagic     why;
-                uintptr_t      uintptr;
-            } payload;
-#  if MOZ_LITTLE_ENDIAN
-            JSValueTag tag;
-#  endif // MOZ_LITTLE_ENDIAN
-#endif // defined(JS_PUNBOX64)
-        } s;
-
-        layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
-        explicit constexpr layout(uint64_t bits) : asBits(bits) {}
-        explicit constexpr layout(double d) : asDouble(d) {}
-    } data;
-
-  private:
-    explicit constexpr Value(uint64_t asBits) : data(asBits) {}
-    explicit constexpr Value(double d) : data(d) {}
-
-    void staticAssertions() {
-        JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
-        JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
-        JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
-        JS_STATIC_ASSERT(sizeof(Value) == 8);
-    }
-
-    friend constexpr Value JS::UndefinedValue();
-
-  public:
-    static constexpr uint64_t
-    bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
-    {
-#if defined(JS_NUNBOX32)
-        return (uint64_t(uint32_t(tag)) << 32) | payload;
-#elif defined(JS_PUNBOX64)
-        return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
-#endif
-    }
-
-    static constexpr Value
-    fromTagAndPayload(JSValueTag tag, PayloadType payload)
-    {
-        return fromRawBits(bitsFromTagAndPayload(tag, payload));
-    }
-
-    static constexpr Value
-    fromRawBits(uint64_t asBits) {
-        return Value(asBits);
-    }
-
-    static constexpr Value
-    fromInt32(int32_t i) {
-        return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
-    }
-
-    static constexpr Value
-    fromDouble(double d) {
-        return Value(d);
-    }
 } JS_HAZ_GC_POINTER;
 
 /**
  * This is a null-constructible structure that can convert to and from
  * a Value, allowing UninitializedValue to be stored in unions.
  */
 struct MOZ_NON_PARAM alignas(8) UninitializedValue
 {
@@ -1263,17 +1243,17 @@ PrivateGCThingValue(js::gc::Cell* cell)
 inline bool
 SameType(const Value& lhs, const Value& rhs)
 {
 #if defined(JS_NUNBOX32)
     JSValueTag ltag = lhs.toTag(), rtag = rhs.toTag();
     return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
 #elif defined(JS_PUNBOX64)
     return (lhs.isDouble() && rhs.isDouble()) ||
-           (((lhs.data.asBits ^ rhs.data.asBits) & 0xFFFF800000000000ULL) == 0);
+           (((lhs.asBits_ ^ rhs.asBits_) & 0xFFFF800000000000ULL) == 0);
 #endif
 }
 
 } // namespace JS
 
 /************************************************************************/
 
 namespace JS {
--- a/js/src/builtin/Object.h
+++ b/js/src/builtin/Object.h
@@ -8,17 +8,17 @@
 #define builtin_Object_h
 
 #include "jsapi.h"
 
 #include "vm/NativeObject.h"
 
 namespace JS {
 class CallArgs;
-class Value;
+union Value;
 } // namespace JS
 
 namespace js {
 
 // Object constructor native. Exposed only so the JIT can know its address.
 MOZ_MUST_USE bool
 obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
 
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -469,16 +469,25 @@ MOZ_MUST_USE MOZ_ALWAYS_INLINE bool
 TokenStreamAnyChars::internalUpdateLineInfoForEOL(uint32_t lineStartOffset)
 {
     prevLinebase = linebase;
     linebase = lineStartOffset;
     lineno++;
     return srcCoords.add(lineno, linebase);
 }
 
+void
+TokenStreamAnyChars::undoInternalUpdateLineInfoForEOL()
+{
+    MOZ_ASSERT(prevLinebase != size_t(-1)); // we should never get more than one EOL
+    linebase = prevLinebase;
+    prevLinebase = size_t(-1);
+    lineno--;
+}
+
 template<typename CharT, class AnyCharsAccess>
 MOZ_MUST_USE MOZ_ALWAYS_INLINE bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::updateLineInfoForEOL()
 {
     return anyCharsAccess().internalUpdateLineInfoForEOL(userbuf.offset());
 }
 
 MOZ_ALWAYS_INLINE void
@@ -540,25 +549,16 @@ GeneralTokenStreamChars<CharT, AnyCharsA
 {
     if (MOZ_LIKELY(userbuf.hasRawChars()))
         return userbuf.getRawChar();
 
     anyCharsAccess().flags.isEOF = true;
     return EOF;
 }
 
-void
-TokenStreamAnyChars::undoGetChar()
-{
-    MOZ_ASSERT(prevLinebase != size_t(-1)); // we should never get more than one EOL
-    linebase = prevLinebase;
-    prevLinebase = size_t(-1);
-    lineno--;
-}
-
 template<typename CharT, class AnyCharsAccess>
 void
 GeneralTokenStreamChars<CharT, AnyCharsAccess>::ungetChar(int32_t c)
 {
     if (c == EOF)
         return;
 
     MOZ_ASSERT(!userbuf.atStart());
@@ -568,17 +568,17 @@ GeneralTokenStreamChars<CharT, AnyCharsA
         int32_t c2 = userbuf.peekRawChar();
         MOZ_ASSERT(TokenBuf::isRawEOLChar(c2));
 #endif
 
         // If it's a \r\n sequence, also unget the \r.
         if (!userbuf.atStart())
             userbuf.matchRawCharBackwards('\r');
 
-        anyCharsAccess().undoGetChar();
+        anyCharsAccess().undoInternalUpdateLineInfoForEOL();
     } else {
         MOZ_ASSERT(userbuf.peekRawChar() == c);
     }
 }
 
 template<typename CharT>
 void
 TokenStreamCharsBase<CharT>::ungetCharIgnoreEOL(int32_t c)
@@ -602,34 +602,29 @@ TokenStreamChars<char16_t, AnyCharsAcces
 
     MOZ_ASSERT(numUnits == 1 || numUnits == 2);
 
     while (numUnits-- > 0)
         ungetCharIgnoreEOL(units[numUnits]);
 }
 
 // Return true iff |n| raw characters can be read from this without reading past
-// EOF or a newline, and copy those characters into |cp| if so.  The characters
-// are not consumed: use skipChars(n) to do so after checking that the consumed
+// EOF, and copy those characters into |cp| if so.  The characters are not
+// consumed: use skipChars(n) to do so after checking that the consumed
 // characters had appropriate values.
 template<typename CharT, class AnyCharsAccess>
 bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::peekChars(int n, CharT* cp)
 {
     int i;
     for (i = 0; i < n; i++) {
         int32_t c = getCharIgnoreEOL();
         if (c == EOF)
             break;
 
-        if (c == '\n') {
-            ungetCharIgnoreEOL(c);
-            break;
-        }
-
         cp[i] = char16_t(c);
     }
 
     for (int j = i - 1; j >= 0; j--)
         ungetCharIgnoreEOL(cp[j]);
 
     return i == n;
 }
@@ -1184,25 +1179,20 @@ TokenStreamSpecific<CharT, AnyCharsAcces
         if (c == EOF || unicode::IsSpaceOrBOM2(c))
             break;
 
         consumeKnownChar(c);
 
         // Debugging directives can occur in both single- and multi-line
         // comments. If we're currently inside a multi-line comment, we also
         // need to recognize multi-line comment terminators.
-        if (isMultiline && c == '*') {
-            int32_t c2;
-            if (!peekChar(&c2))
-                return false;
-
-            if (c2 == '/') {
-                ungetChar('*');
-                break;
-            }
+        if (isMultiline && c == '*' && matchChar('/')) {
+            ungetCharIgnoreEOL('/');
+            ungetCharIgnoreEOL('*');
+            break;
         }
 
         if (!tokenbuf.append(c))
             return false;
     } while (true);
 
     if (tokenbuf.empty()) {
         // The directive's URL was missing, but this is not quite an
@@ -1383,17 +1373,17 @@ enum FirstCharKind {
     LastCharKind = Other
 };
 
 // OneChar: 40,  41,  44,  58,  59,  63,  91,  93,  123, 125, 126:
 //          '(', ')', ',', ':', ';', '?', '[', ']', '{', '}', '~'
 // Ident:   36, 65..90, 95, 97..122: '$', 'A'..'Z', '_', 'a'..'z'
 // Dot:     46: '.'
 // Equals:  61: '='
-// String:  34, 39: '"', '\''
+// String:  34, 39, 96: '"', '\'', '`'
 // Dec:     49..57: '1'..'9'
 // Plus:    43: '+'
 // BasePrefix:  48: '0'
 // Space:   9, 11, 12, 32: '\t', '\v', '\f', ' '
 // EOL:     10, 13: '\n', '\r'
 //
 #define T_COMMA     size_t(TokenKind::Comma)
 #define T_COLON     size_t(TokenKind::Colon)
@@ -1401,46 +1391,44 @@ enum FirstCharKind {
 #define T_LP        size_t(TokenKind::Lp)
 #define T_RP        size_t(TokenKind::Rp)
 #define T_SEMI      size_t(TokenKind::Semi)
 #define T_HOOK      size_t(TokenKind::Hook)
 #define T_LB        size_t(TokenKind::Lb)
 #define T_RB        size_t(TokenKind::Rb)
 #define T_LC        size_t(TokenKind::Lc)
 #define T_RC        size_t(TokenKind::Rc)
-#define Templat     String
 #define _______     Other
 static const uint8_t firstCharKinds[] = {
 /*         0        1        2        3        4        5        6        7        8        9    */
 /*   0+ */ _______, _______, _______, _______, _______, _______, _______, _______, _______,   Space,
 /*  10+ */     EOL,   Space,   Space,     EOL, _______, _______, _______, _______, _______, _______,
 /*  20+ */ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
 /*  30+ */ _______, _______,   Space, _______,  String, _______,   Ident, _______, _______,  String,
-/*  40+ */    T_LP,    T_RP, _______, _______, T_COMMA,_______,  _______, _______,BasePrefix,  Dec,
-/*  50+ */     Dec,     Dec,     Dec,     Dec,     Dec,     Dec,     Dec,    Dec,  T_COLON,  T_SEMI,
+/*  40+ */    T_LP,    T_RP, _______, _______, T_COMMA, _______, _______, _______,BasePrefix,   Dec,
+/*  50+ */     Dec,     Dec,     Dec,     Dec,     Dec,     Dec,     Dec,     Dec, T_COLON,  T_SEMI,
 /*  60+ */ _______, _______, _______,  T_HOOK, _______,   Ident,   Ident,   Ident,   Ident,   Ident,
 /*  70+ */   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,
 /*  80+ */   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,
-/*  90+ */   Ident,    T_LB, _______,    T_RB, _______,   Ident, Templat,   Ident,   Ident,   Ident,
+/*  90+ */   Ident,    T_LB, _______,    T_RB, _______,   Ident,  String,   Ident,   Ident,   Ident,
 /* 100+ */   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,
 /* 110+ */   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,   Ident,
 /* 120+ */   Ident,   Ident,   Ident,    T_LC, _______,    T_RC,T_BITNOT, _______
 };
 #undef T_COMMA
 #undef T_COLON
 #undef T_BITNOT
 #undef T_LP
 #undef T_RP
 #undef T_SEMI
 #undef T_HOOK
 #undef T_LB
 #undef T_RB
 #undef T_LC
 #undef T_RC
-#undef Templat
 #undef _______
 
 static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)),
               "Elements of firstCharKinds[] are too small");
 
 template<typename CharT, class AnyCharsAccess>
 MOZ_MUST_USE bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Modifier modifier)
@@ -1892,19 +1880,19 @@ TokenStreamSpecific<CharT, AnyCharsAcces
 
       case '<':
         if (anyCharsAccess().options().allowHTMLComments) {
             // Treat HTML begin-comment as comment-till-end-of-line.
             if (matchChar('!')) {
                 if (matchChar('-')) {
                     if (matchChar('-'))
                         goto skipline;
-                    ungetChar('-');
+                    ungetCharIgnoreEOL('-');
                 }
-                ungetChar('!');
+                ungetCharIgnoreEOL('!');
             }
         }
         if (matchChar('<')) {
             tp->type = matchChar('=') ? TokenKind::LshAssign : TokenKind::Lsh;
         } else {
             tp->type = matchChar('=') ? TokenKind::Le : TokenKind::Lt;
         }
         goto out;
@@ -1925,33 +1913,31 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             tp->type = matchChar('=') ? TokenKind::PowAssign : TokenKind::Pow;
         else
             tp->type = matchChar('=') ? TokenKind::MulAssign : TokenKind::Mul;
         goto out;
 
       case '/':
         // Look for a single-line comment.
         if (matchChar('/')) {
-            if (!peekChar(&c))
-                goto error;
+            c = getCharIgnoreEOL();
             if (c == '@' || c == '#') {
-                consumeKnownChar(c);
-
                 bool shouldWarn = c == '@';
                 if (!getDirectives(false, shouldWarn))
                     goto error;
+            } else {
+                ungetCharIgnoreEOL(c);
             }
 
         skipline:
             do {
-                if (!getChar(&c))
-                    goto error;
-            } while (c != EOF && c != '\n');
+                c = getCharIgnoreEOL();
+            } while (c != EOF && !TokenBuf::isRawEOLChar(c));
 
-            ungetChar(c);
+            ungetCharIgnoreEOL(c);
             anyCharsAccess().cursor = (anyCharsAccess().cursor - 1) & ntokensMask;
             goto retry;
         }
 
         // Look for a multi-line comment.
         if (matchChar('*')) {
             TokenStreamAnyChars& anyChars = anyCharsAccess();
             unsigned linenoBefore = anyChars.lineno;
@@ -2008,47 +1994,44 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                     reportError(JSMSG_UNTERMINATED_REGEXP);
                     goto error;
                 }
                 if (!tokenbuf.append(c))
                     goto error;
             } while (true);
 
             RegExpFlag reflags = NoFlags;
-            unsigned length = tokenbuf.length() + 1;
             while (true) {
-                if (!peekChar(&c))
-                    goto error;
-                if (c == 'g' && !(reflags & GlobalFlag))
-                    reflags = RegExpFlag(reflags | GlobalFlag);
-                else if (c == 'i' && !(reflags & IgnoreCaseFlag))
-                    reflags = RegExpFlag(reflags | IgnoreCaseFlag);
-                else if (c == 'm' && !(reflags & MultilineFlag))
-                    reflags = RegExpFlag(reflags | MultilineFlag);
-                else if (c == 'y' && !(reflags & StickyFlag))
-                    reflags = RegExpFlag(reflags | StickyFlag);
-                else if (c == 'u' && !(reflags & UnicodeFlag))
-                    reflags = RegExpFlag(reflags | UnicodeFlag);
+                RegExpFlag flag;
+                c = getCharIgnoreEOL();
+                if (c == 'g')
+                    flag = GlobalFlag;
+                else if (c == 'i')
+                    flag = IgnoreCaseFlag;
+                else if (c == 'm')
+                    flag = MultilineFlag;
+                else if (c == 'y')
+                    flag = StickyFlag;
+                else if (c == 'u')
+                    flag = UnicodeFlag;
+                else if (JS7_ISLET(c))
+                    flag = NoFlags;
                 else
                     break;
-                if (!getChar(&c))
-                    goto error;
-                length++;
-            }
 
-            if (!peekChar(&c))
-                goto error;
-            if (JS7_ISLET(c)) {
-                char buf[2] = { '\0', '\0' };
-                tp->pos.begin += length + 1;
-                buf[0] = char(c);
-                reportError(JSMSG_BAD_REGEXP_FLAG, buf);
-                consumeKnownChar(c);
-                goto error;
+                if ((reflags & flag) || flag == NoFlags) {
+                    MOZ_ASSERT(userbuf.offset() > 0);
+                    char buf[2] = { char(c), '\0' };
+                    errorAt(userbuf.offset() - 1, JSMSG_BAD_REGEXP_FLAG, buf);
+                    goto error;
+                }
+                reflags = RegExpFlag(reflags | flag);
             }
+            ungetCharIgnoreEOL(c);
+
             tp->type = TokenKind::RegExp;
             tp->setRegExpFlags(reflags);
             goto out;
         }
 
         tp->type = matchChar('=') ? TokenKind::DivAssign : TokenKind::Div;
         goto out;
 
@@ -2056,21 +2039,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
         tp->type = matchChar('=') ? TokenKind::ModAssign : TokenKind::Mod;
         goto out;
 
       case '-':
         if (matchChar('-')) {
             if (anyCharsAccess().options().allowHTMLComments &&
                 !anyCharsAccess().flags.isDirtyLine)
             {
-                int32_t c2;
-                if (!peekChar(&c2))
-                    goto error;
-
-                if (c2 == '>')
+                if (matchChar('>'))
                     goto skipline;
             }
 
             tp->type = TokenKind::Dec;
         } else {
             tp->type = matchChar('=') ? TokenKind::SubAssign : TokenKind::Sub;
         }
         goto out;
@@ -2118,19 +2097,19 @@ TokenStreamSpecific<CharT, AnyCharsAcces
 template<typename CharT, class AnyCharsAccess>
 bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(char untilChar, Token** tp)
 {
     MOZ_ASSERT(untilChar == '\'' || untilChar == '"' || untilChar == '`',
                "unexpected string/template literal delimiter");
 
     int c;
-    int nc = -1;
 
     bool parsingTemplate = (untilChar == '`');
+    bool templateHead = false;
 
     *tp = newToken(-1);
     tokenbuf.clear();
 
     // We need to detect any of these chars:  " or ', \n (or its
     // equivalents), \\, EOF.  Because we detect EOL sequences here and
     // put them back immediately, we can use getCharIgnoreEOL().
     while ((c = getCharIgnoreEOL()) != untilChar) {
@@ -2165,27 +2144,20 @@ TokenStreamSpecific<CharT, AnyCharsAcces
 
               case '\n':
                 // ES5 7.8.4: an escaped line terminator represents
                 // no character.
                 continue;
 
               // Unicode character specification.
               case 'u': {
-                uint32_t code = 0;
-
-                int32_t c2;
-                if (!peekChar(&c2))
-                    return false;
-
-                uint32_t start = userbuf.offset() - 2;
-
+                int32_t c2 = getCharIgnoreEOL();
                 if (c2 == '{') {
-                    consumeKnownChar('{');
-
+                    uint32_t start = userbuf.offset() - 3;
+                    uint32_t code = 0;
                     bool first = true;
                     bool valid = true;
                     do {
                         int32_t c = getCharIgnoreEOL();
                         if (c == EOF) {
                             if (parsingTemplate) {
                                 TokenStreamAnyChars& anyChars = anyCharsAccess();
                                 anyChars.setInvalidTemplateEscape(start,
@@ -2253,26 +2225,28 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                     } else {
                         if (!tokenbuf.append(unicode::LeadSurrogate(code)))
                             return false;
                         c = unicode::TrailSurrogate(code);
                     }
                     break;
                 }
 
-                CharT cp[4];
-                if (peekChars(4, cp) &&
-                    JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3]))
+                CharT cp[3];
+                if (JS7_ISHEX(c2) && peekChars(3, cp) &&
+                    JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]))
                 {
-                    c = JS7_UNHEX(cp[0]);
-                    c = (c << 4) + JS7_UNHEX(cp[1]);
-                    c = (c << 4) + JS7_UNHEX(cp[2]);
-                    c = (c << 4) + JS7_UNHEX(cp[3]);
-                    skipChars(4);
+                    c = (JS7_UNHEX(c2) << 12) |
+                        (JS7_UNHEX(cp[0]) << 8) |
+                        (JS7_UNHEX(cp[1]) << 4) |
+                        JS7_UNHEX(cp[2]);
+                    skipChars(3);
                 } else {
+                    ungetCharIgnoreEOL(c2);
+                    uint32_t start = userbuf.offset() - 2;
                     if (parsingTemplate) {
                         TokenStreamAnyChars& anyChars = anyCharsAccess();
                         anyChars.setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
                         continue;
                     }
                     reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
                     return false;
                 }
@@ -2342,44 +2316,47 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             if (!parsingTemplate) {
                 ungetCharIgnoreEOL(c);
                 const char delimiters[] = { untilChar, untilChar, '\0' };
                 error(JSMSG_EOL_BEFORE_END_OF_STRING, delimiters);
                 return false;
             }
             if (c == '\r') {
                 c = '\n';
-                if (userbuf.peekRawChar() == '\n')
-                    skipCharsIgnoreEOL(1);
+
+                // If it's a \r\n sequence: treat as a single EOL, skip over the \n.
+                if (userbuf.hasRawChars())
+                    userbuf.matchRawChar('\n');
             }
 
             if (!updateLineInfoForEOL())
                 return false;
 
             anyCharsAccess().updateFlagsForEOL();
-        } else if (parsingTemplate && c == '$') {
-            if ((nc = getCharIgnoreEOL()) == '{')
-                break;
-            ungetCharIgnoreEOL(nc);
+        } else if (parsingTemplate && c == '$' && matchChar('{')) {
+            templateHead = true;
+            break;
         }
 
         if (!tokenbuf.append(c)) {
             ReportOutOfMemory(anyCharsAccess().cx);
             return false;
         }
     }
 
     JSAtom* atom = atomizeChars(anyCharsAccess().cx, tokenbuf.begin(), tokenbuf.length());
     if (!atom)
         return false;
 
     if (!parsingTemplate) {
+        MOZ_ASSERT(!templateHead);
+
         (*tp)->type = TokenKind::String;
     } else {
-        if (c == '$' && nc == '{')
+        if (templateHead)
             (*tp)->type = TokenKind::TemplateHead;
         else
             (*tp)->type = TokenKind::NoSubsTemplate;
     }
 
     (*tp)->setAtom(atom);
     return true;
 }
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -515,18 +515,16 @@ class TokenStreamAnyChars
 
     bool getMutedErrors() const { return mutedErrors; }
 
     MOZ_MUST_USE bool checkOptions();
 
   private:
     PropertyName* reservedWordToPropertyName(TokenKind tt) const;
 
-    void undoGetChar();
-
   public:
     PropertyName* currentName() const {
         if (isCurrentTokenType(TokenKind::Name))
             return currentToken().name();
 
         MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
         return reservedWordToPropertyName(currentToken().type);
     }
@@ -744,16 +742,18 @@ class TokenStreamAnyChars
      */
     bool fillExcludingContext(ErrorMetadata* err, uint32_t offset);
 
     void updateFlagsForEOL();
 
   private:
     MOZ_MUST_USE MOZ_ALWAYS_INLINE bool internalUpdateLineInfoForEOL(uint32_t lineStartOffset);
 
+    void undoInternalUpdateLineInfoForEOL();
+
   public:
     const Token& nextToken() const {
         MOZ_ASSERT(hasLookahead());
         return tokens[(cursor + 1) & ntokensMask];
     }
 
     bool hasLookahead() const { return lookahead > 0; }
 
@@ -1478,17 +1478,17 @@ class MOZ_STACK_CLASS TokenStreamSpecifi
         ungetChar(*c);
         return true;
     }
 
     void skipChars(uint32_t n) {
         while (n-- > 0) {
             MOZ_ASSERT(userbuf.hasRawChars());
             mozilla::DebugOnly<int32_t> c = getCharIgnoreEOL();
-            MOZ_ASSERT(c != '\n');
+            MOZ_ASSERT(!TokenBuf::isRawEOLChar(c));
         }
     }
 
     void skipCharsIgnoreEOL(uint8_t n) {
         while (n-- > 0) {
             MOZ_ASSERT(userbuf.hasRawChars());
             getCharIgnoreEOL();
         }
--- a/js/src/gdb/mozilla/jsval.py
+++ b/js/src/gdb/mozilla/jsval.py
@@ -5,21 +5,19 @@ import gdb.types
 import mozilla.prettyprinters
 from mozilla.prettyprinters import pretty_printer, ptr_pretty_printer
 
 # Forget any printers from previous loads of this module.
 mozilla.prettyprinters.clear_module_printers(__name__)
 
 # Summary of the JS::Value type:
 #
-# Viewed abstractly, JS::Value is a 64-bit discriminated union, with
-# JSString *, JSObject *, IEEE 64-bit floating-point, and 32-bit integer
-# branches (and a few others). (It is not actually a C++ union;
-# 'discriminated union' just describes the overall effect.) Note that
-# JS::Value is always 64 bits long, even on 32-bit architectures.
+# JS::Value is a 64-bit discriminated union, with JSString*, JSObject*, IEEE
+# 64-bit floating-point, and 32-bit integer branches (and a few others).
+# JS::Value is 64 bits long on all architectures.
 #
 # The ECMAScript standard specifies that ECMAScript numbers are IEEE 64-bit
 # floating-point values. A JS::Value can represent any JavaScript number
 # value directly, without referring to additional storage, or represent an
 # object, string, or other ECMAScript value, and remember which type it is.
 # This may seem surprising: how can a 64-bit type hold all the 64-bit IEEE
 # values, and still distinguish them from objects, strings, and so on,
 # which have 64-bit addresses?
@@ -58,30 +56,29 @@ mozilla.prettyprinters.clear_module_prin
 # - Any bitstring that IEEE calls a NaN represents either an ECMAScript NaN
 #   or a non-number ECMAScript value, as determined by a tag field stored
 #   towards the most significant end of the fraction field (exactly where
 #   depends on the address size). If the tag field indicates that this
 #   JS::Value is an object, the fraction field's least significant end
 #   holds the address of a JSObject; if a string, the address of a
 #   JSString; and so on.
 #
-# On the only 64-bit platform we support, x86_64, only the lower 48 bits of
-# an address are significant, and only those values whose top bit is zero
-# are used for user-space addresses. This means that x86_64 addresses are
-# effectively 47 bits long, and thus fit nicely in the available portion of
-# the fraction field.
+# On x86_64 only the lower 48 bits of an address are significant, and only
+# those values whose top bit is zero are used for user-space addresses. Thus
+# x86_64 addresses are effectively 47 bits long and fit nicely in the available
+# portion of the fraction field.
 #
 # See Value.h for full details.
 
 class Box(object):
     def __init__(self, asBits, jtc):
         self.asBits = asBits
         self.jtc = jtc
-        # Value::layout::asBits is uint64_t, but somehow the sign bit can be
-        # botched here, even though Python integers are arbitrary precision.
+        # Value::asBits is uint64_t, but somehow the sign bit can be botched
+        # here, even though Python integers are arbitrary precision.
         if self.asBits < 0:
             self.asBits = self.asBits + (1 << 64)
 
     # Return this value's type tag.
     def tag(self): raise NotImplementedError
 
     # Return this value as a 32-bit integer, double, or address.
     def as_uint32(self): raise NotImplementedError
@@ -162,19 +159,18 @@ class JSValueTypeCache(object):
 class JSValue(object):
     def __init__(self, value, cache):
         # Save the generic typecache, and create our own, if we haven't already.
         self.cache = cache
         if not cache.mod_JS_Value:
             cache.mod_JS_Value = JSValueTypeCache(cache)
         self.jtc = cache.mod_JS_Value
 
-        data = value['data']
-        self.data = data
-        self.box = self.jtc.boxer(data['asBits'], self.jtc)
+        self.value = value
+        self.box = self.jtc.boxer(value['asBits_'], self.jtc)
 
     def to_string(self):
         tag = self.box.tag()
 
         if tag == self.jtc.UNDEFINED:
             return '$JS::UndefinedValue()'
         if tag == self.jtc.NULL:
             return '$JS::NullValue()'
@@ -189,17 +185,17 @@ class JSValue(object):
 
         if tag == self.jtc.INT32:
             value = self.box.as_uint32()
             signbit = 1 << 31
             value = (value ^ signbit) - signbit
             return '$JS::Int32Value(%s)' % value
 
         if tag == self.jtc.DOUBLE:
-            return '$JS::DoubleValue(%s)' % self.data['asDouble']
+            return '$JS::DoubleValue(%s)' % self.value['asDouble_']
 
         if tag == self.jtc.STRING:
             value = self.box.as_address().cast(self.cache.JSString_ptr_t)
         elif tag == self.jtc.OBJECT:
             value = self.box.as_address().cast(self.cache.JSObject_ptr_t)
         elif tag == self.jtc.SYMBOL:
             value = self.box.as_address().cast(self.cache.JSSymbol_ptr_t)
         else:
--- a/js/src/gdb/mozilla/prettyprinters.py
+++ b/js/src/gdb/mozilla/prettyprinters.py
@@ -206,30 +206,33 @@ class TypeCache(object):
 # class hierarchy).
 def implemented_types(t):
 
     # Yield all types that follow |t|.
     def followers(t):
         if t.code == gdb.TYPE_CODE_TYPEDEF:
             yield t.target()
             for t2 in followers(t.target()): yield t2
-        elif t.code == gdb.TYPE_CODE_STRUCT:
+        elif is_struct_or_union(t):
             base_classes = []
             for f in t.fields():
                 if f.is_base_class:
                     yield f.type
                     base_classes.append(f.type)
             for b in base_classes:
                 for t2 in followers(b): yield t2
 
     yield t
     for t2 in followers(t): yield t2
 
 template_regexp = re.compile("([\w_:]+)<")
 
+def is_struct_or_union(t):
+    return t.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION)
+
 # Construct and return a pretty-printer lookup function for objfile, or
 # return None if the objfile doesn't contain SpiderMonkey code
 # (specifically, definitions for SpiderMonkey types).
 def lookup_for_objfile(objfile):
     # Create a type cache for this objfile.
     try:
         cache = TypeCache(objfile)
     except NotSpiderMonkeyObjfileError:
@@ -248,34 +251,34 @@ def lookup_for_objfile(objfile):
                 f = table[tag]
                 if f.enabled:
                     return f(value, cache)
             return None
 
         def check_table_by_type_name(table, t):
             if t.code == gdb.TYPE_CODE_TYPEDEF:
                 return check_table(table, str(t))
-            elif t.code == gdb.TYPE_CODE_STRUCT and t.tag:
+            elif is_struct_or_union(t) and t.tag:
                 return check_table(table, t.tag)
             else:
                 return None
 
         for t in implemented_types(value.type):
             if t.code == gdb.TYPE_CODE_PTR:
                 for t2 in implemented_types(t.target()):
                     p = check_table_by_type_name(ptr_printers_by_tag, t2)
                     if p: return p
             elif t.code == gdb.TYPE_CODE_REF:
                 for t2 in implemented_types(t.target()):
                     p = check_table_by_type_name(ref_printers_by_tag, t2)
                     if p: return p
             else:
                 p = check_table_by_type_name(printers_by_tag, t)
                 if p: return p
-                if t.code == gdb.TYPE_CODE_STRUCT and t.tag:
+                if is_struct_or_union(t) and t.tag:
                     m = template_regexp.match(t.tag)
                     if m:
                         p = check_table(template_printers_by_tag, m.group(1))
                         if p: return p
 
         # Failing that, look for a printer in printers_by_regexp. We have
         # to scan the whole list, so regexp printers should be used
         # sparingly.
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -926,17 +926,17 @@ TraceIonJSFrame(JSTracer* trc, const JSJ
         JSValueTag tag = JSValueTag(ReadAllocation(frame, &type));
         uintptr_t rawPayload = ReadAllocation(frame, &payload);
 
         Value v = Value::fromTagAndPayload(tag, rawPayload);
         TraceRoot(trc, &v, "ion-torn-value");
 
         if (v != Value::fromTagAndPayload(tag, rawPayload)) {
             // GC moved the value, replace the stored payload.
-            rawPayload = *v.payloadUIntPtr();
+            rawPayload = v.toNunboxPayload();
             WriteAllocation(frame, &payload, rawPayload);
         }
     }
 #endif
 }
 
 static void
 TraceBailoutFrame(JSTracer* trc, const JSJitFrameIter& frame)
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -479,25 +479,16 @@ interface nsIXPCComponents_Utils : nsISu
      * For gecko internal automation use only. Calling this in production code
      * would result in security vulnerabilities, so it will crash if used outside
      * of automation.
      */
     [implicit_jscontext]
     void forcePermissiveCOWs();
 
     /*
-     * This seemingly-paradoxical API allows privileged code to explicitly give
-     * unprivileged code a reference to its own Components object (whereas it's
-     * normally hidden away on a scope chain visible only to XBL methods). See
-     * also SpecialPowers.getComponents.
-     */
-    [implicit_jscontext]
-    jsval getComponentsForScope(in jsval vscope);
-
-    /*
      * Dispatches a runnable to the current/main thread. If |scope| is passed,
      * the runnable will be dispatch in the compartment of |scope|, which
      * affects which error reporter gets called.
      */
     [implicit_jscontext]
     void dispatch(in jsval runnable, [optional] in jsval scope);
 
     /*
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -158,19 +158,17 @@ nsXPCComponents_Interfaces::GetClassID(n
 {
     *aClassID = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Interfaces::GetFlags(uint32_t* aFlags)
 {
-    // Mark ourselves as a DOM object so that instances may be created in
-    // unprivileged scopes.
-    *aFlags = nsIClassInfo::DOM_OBJECT;
+    *aFlags = 0;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
@@ -358,19 +356,17 @@ nsXPCComponents_InterfacesByID::GetClass
 {
     *aClassID = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetFlags(uint32_t* aFlags)
 {
-    // Mark ourselves as a DOM object so that instances may be created in
-    // unprivileged scopes.
-    *aFlags = nsIClassInfo::DOM_OBJECT;
+    *aFlags = 0;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
@@ -952,19 +948,17 @@ nsXPCComponents_Results::GetClassID(nsCI
 {
     *aClassID = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Results::GetFlags(uint32_t* aFlags)
 {
-    // Mark ourselves as a DOM object so that instances may be created in
-    // unprivileged scopes.
-    *aFlags = nsIClassInfo::DOM_OBJECT;
+    *aFlags = 0;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Results::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
@@ -2679,33 +2673,16 @@ nsXPCComponents_Utils::ForcePermissiveCO
     JSObject* currentGlobal = CurrentGlobalOrNull(cx);
     MOZ_DIAGNOSTIC_ASSERT(!mozJSComponentLoader::Get()->IsLoaderGlobal(currentGlobal),
                           "Don't call Cu.forcePermissiveCOWs() in a JSM that shares its global");
     CompartmentPrivate::Get(currentGlobal)->forcePermissiveCOWs = true;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext* cx,
-                                             MutableHandleValue rval)
-{
-    if (!vscope.isObject())
-        return NS_ERROR_INVALID_ARG;
-    JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
-    XPCWrappedNativeScope* scope = ObjectScope(scopeObj);
-    RootedObject components(cx);
-    if (!scope->GetComponentsJSObject(&components))
-        return NS_ERROR_FAILURE;
-    if (!JS_WrapObject(cx, &components))
-        return NS_ERROR_FAILURE;
-    rval.setObject(*components);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
                                 JSContext* cx)
 {
     RootedValue runnable(cx, runnableArg);
     // Enter the given compartment, if any, and rewrap runnable.
     Maybe<JSAutoCompartment> ac;
     if (scope.isObject()) {
         JSObject* scopeObj = js::UncheckedUnwrap(&scope.toObject());
@@ -3260,20 +3237,20 @@ NS_IMPL_QUERY_INTERFACE(ComponentsSH, ns
 #define NSXPCCOMPONENTSBASE_CID \
 { 0xc62998e5, 0x95f1, 0x4058, \
   { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
 
 #define NSXPCCOMPONENTS_CID \
 { 0x3649f405, 0xf0ec, 0x4c28, \
     { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
 
-NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
+NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, 0, NSXPCCOMPONENTSBASE_CID)
 NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
 
-NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
+NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, 0, NSXPCCOMPONENTS_CID)
 // Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
 // if it existed.
 NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
 NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
     NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
     NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
 NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -262,22 +262,17 @@ DefinePropertyIfFound(XPCCallContext& cc
 
                 if (classInfo) {
                     nsresult rv = classInfo->GetFlags(&flags);
                     if (NS_FAILED(rv))
                         return Throw(rv, ccx);
                 }
             }
 
-            bool overwriteToString = !(flags & nsIClassInfo::DOM_OBJECT)
-                || Preferences::GetBool("dom.XPCToStringForDOMClasses", false);
-
-            if(id == xpccx->GetStringID(XPCJSContext::IDX_TO_STRING)
-                && overwriteToString)
-            {
+            if (id == xpccx->GetStringID(XPCJSContext::IDX_TO_STRING)) {
                 call = XPC_WN_Shared_ToString;
                 name = xpccx->GetStringName(XPCJSContext::IDX_TO_STRING);
             } else if (id == xpccx->GetStringID(XPCJSContext::IDX_TO_SOURCE)) {
                 call = XPC_WN_Shared_ToSource;
                 name = xpccx->GetStringName(XPCJSContext::IDX_TO_SOURCE);
             } else if (id == SYMBOL_TO_JSID(
                                JS::GetWellKnownSymbol(ccx, JS::SymbolCode::toPrimitive)))
             {
--- a/js/xpconnect/tests/unit/test_allowedDomains.js
+++ b/js/xpconnect/tests/unit/test_allowedDomains.js
@@ -33,14 +33,9 @@ function run_test() {
     } catch (e) {    
       Assert.ok(e.message && e.message.includes("Permission denied to access property"));
     }  
   }
   
   evalAndCatch("objC.prop1", sbMaster);
   evalAndCatch("objMaster.prop1", sbA);
   evalAndCatch("objMaster.prop1", sbSubset);
-  
-  // Bug 777705:
-  sbMaster.Components = Cu.getComponentsForScope(sbMaster);
-  Cu.evalInSandbox("Components.interfaces", sbMaster);
-  Assert.ok(true);
 }
--- a/js/xpconnect/tests/unit/test_components.js
+++ b/js/xpconnect/tests/unit/test_components.js
@@ -1,52 +1,24 @@
 function run_test() {
   var sb1 = Cu.Sandbox("http://www.blah.com");
-  var sb2 = Cu.Sandbox("http://www.blah.com");
-  var sb3 = Cu.Sandbox(this);
-  var sb4 = Cu.Sandbox("http://www.other.com");
+  var sb2 = Cu.Sandbox(this);
   var rv;
 
-  // Components is normally hidden from content on the XBL scope chain, but we
-  // expose it to content here to make sure that the security wrappers work
-  // regardless.
-  [sb1, sb2, sb4].forEach(function(x) { x.Components = Cu.getComponentsForScope(x); });
-
   // non-chrome accessing chrome Components
   sb1.C = Components;
+  checkThrows("C.interfaces", sb1);
   checkThrows("C.utils", sb1);
   checkThrows("C.classes", sb1);
 
-  // non-chrome accessing own Components
-  Assert.equal(Cu.evalInSandbox("typeof Components.interfaces", sb1), 'object');
-  Assert.equal(Cu.evalInSandbox("typeof Components.utils", sb1), 'undefined');
-  Assert.equal(Cu.evalInSandbox("typeof Components.classes", sb1), 'undefined');
-
-  // Make sure an unprivileged Components is benign.
-  var C2 = Cu.evalInSandbox("Components", sb2);
-  var whitelist = ['interfaces', 'interfacesByID', 'results', 'isSuccessCode', 'QueryInterface'];
-  for (var prop in Components) {
-    info("Checking " + prop);
-    Assert.equal((prop in C2), whitelist.includes(prop));
-  }
-
-  // non-chrome same origin
-  sb1.C2 = C2;
-  Assert.equal(Cu.evalInSandbox("typeof C2.interfaces", sb1), 'object');
-  Assert.equal(Cu.evalInSandbox("typeof C2.utils", sb1), 'undefined');
-  Assert.equal(Cu.evalInSandbox("typeof C2.classes", sb1), 'undefined');
+  // non-chrome accessing own Components: shouldn't exist.
+  Assert.equal(Cu.evalInSandbox("typeof Components", sb1), 'undefined');
 
   // chrome accessing chrome
-  sb3.C = Components;
-  rv = Cu.evalInSandbox("C.utils", sb3);
+  sb2.C = Components;
+  rv = Cu.evalInSandbox("C.utils", sb2);
   Assert.equal(rv, Cu);
-
-  // non-chrome cross origin
-  sb4.C2 = C2;
-  checkThrows("C2.interfaces", sb4);
-  checkThrows("C2.utils", sb4);
-  checkThrows("C2.classes", sb4);
 }
 
 function checkThrows(expression, sb) {
   var result = Cu.evalInSandbox('(function() { try { ' + expression + '; return "allowed"; } catch (e) { return e.toString(); }})();', sb);
   Assert.ok(!!/denied/.exec(result));
 }
--- a/layout/forms/test/test_bug348236.html
+++ b/layout/forms/test/test_bug348236.html
@@ -33,17 +33,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="text/javascript">
 
   /** Test for Bug 348236 **/
 
 SimpleTest.waitForExplicitFinish()
 addLoadEvent(function test() {
 
     var
-        CI = SpecialPowers.Components.interfaces,
         WinUtils = SpecialPowers.getDOMWindowUtils(window),
         sec = netscape.security,
         eSelect = $("eSelect"),
         timeout = 0 // Choose a larger value like 500 ms if you want to see what's happening.
 
     function keypressOnSelect(key) {
         eSelect.focus();
         synthesizeKey(key.key, {altKey: key.altKey});
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5683,31 +5683,19 @@ nsFrame::ComputeSize(gfxContext*        
     usingFlexBasisForISize =
       (flexContainerIsRowOriented == inlineAxisSameAsParent);
 
     // NOTE: The logic here should match the similar chunk for determining
     // inlineStyleCoord and blockStyleCoord in
     // nsFrame::ComputeSizeWithIntrinsicDimensions().
     const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
     if (flexBasis->GetUnit() != eStyleUnit_Auto) {
-      // One caveat for when flex-basis is stomping on 'height': We don't
-      // support enumerated values (e.g. "max-content") for height yet (that's
-      // bug 567039). So, if our computed flex-basis is an enumerated value,
-      // we'll just behave as if it were "auto", which means "use the main-size
-      // property after all" (which is "height", in this case).  NOTE: Once we
-      // support intrinsic sizing keywords for "height", we should remove this
-      // check.
-      bool usingFlexBasisForHeight =
-        (usingFlexBasisForISize != aWM.IsVertical());
-      if (!usingFlexBasisForHeight ||
-          flexBasis->GetUnit() != eStyleUnit_Enumerated) {
-        // Override whichever coord we're overriding:
-        (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
-          flexBasis;
-      }
+      // Override whichever styleCoord is in flex container's main axis:
+      (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
+        flexBasis;
     }
   }
 
   // Compute inline-axis size
   if (inlineStyleCoord->GetUnit() != eStyleUnit_Auto) {
     result.ISize(aWM) =
       ComputeISizeValue(aRenderingContext, aCBSize.ISize(aWM),
                         boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
@@ -5946,31 +5934,19 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
       // Flex items use their "flex-basis" property in place of their main-size
       // property (e.g. "width") for sizing purposes, *unless* they have
       // "flex-basis:auto", in which case they use their main-size property
       // after all.
       // NOTE: The logic here should match the similar chunk for determining
       // inlineStyleCoord and blockStyleCoord in nsFrame::ComputeSize().
       const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
       if (flexBasis->GetUnit() != eStyleUnit_Auto) {
-        // One caveat for when flex-basis is stomping on 'height': We don't
-        // support enumerated values (e.g. "max-content") for height yet
-        // (that's bug 567039). So, if our computed flex-basis is an enumerated
-        // value, we'll just behave as if it were "auto", which means "use the
-        // main-size property after all" (which is "height", in this case).
-        // NOTE: Once we support intrinsic sizing keywords for "height", we
-        // should remove this check.
-        bool usingFlexBasisForHeight =
-          (usingFlexBasisForISize != aWM.IsVertical());
-        if (!usingFlexBasisForHeight ||
-            flexBasis->GetUnit() != eStyleUnit_Enumerated) {
-          // Override whichever coord we're overriding:
-          (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
-            flexBasis;
-        }
+        // Override whichever styleCoord is in flex container's main axis:
+        (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
+          flexBasis;
       }
     }
   }
 
   // Handle intrinsic sizes and their interaction with
   // {min-,max-,}{width,height} according to the rules in
   // http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
 
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/32_add-on-devel.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/32_add-on-devel.py
@@ -5,17 +5,16 @@ config = {
         'clobber',
         'build',
         'check-test',
 #        'update',
     ],
     'stage_platform': 'win32-add-on-devel',
     #### 32 bit build specific #####
     'env': {
-        'BINSCOPE': 'C:/Program Files (x86)/Microsoft/SDL BinScope/BinScope.exe',
         'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
         'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 'C:/mozilla-build/buildbotve/scripts;'
                 '%s' % (os.environ.get('path')),
         'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/32_debug.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/32_debug.py
@@ -6,17 +6,16 @@ config = {
         'build',
         'check-test',
         'update',  # decided by query_is_nightly()
     ],
     'stage_platform': 'win32-debug',
     'debug_build': True,
     #### 32 bit build specific #####
     'env': {
-        'BINSCOPE': 'C:/Program Files (x86)/Microsoft/SDL BinScope/BinScope.exe',
         'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
         'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 'C:/mozilla-build/buildbotve/scripts;'
                 '%s' % (os.environ.get('path')),
         'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/32_stat_and_debug.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/32_stat_and_debug.py
@@ -9,17 +9,16 @@ config = {
     'stage_platform': 'win32-st-an-debug',
     'debug_build': True,
     'enable_signing': False,
     'tooltool_manifest_src': "browser/config/tooltool-manifests/win32/\
 releng.manifest",
     'perfherder_extra_options': ['static-analysis'],
     #### 32 bit build specific #####
     'env': {
-        'BINSCOPE': 'C:/Program Files (x86)/Microsoft/SDL BinScope/BinScope.exe',
         'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
         'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 'C:/mozilla-build/buildbotve/scripts;'
                 '%s' % (os.environ.get('path')),
         'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/64_add-on-devel.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/64_add-on-devel.py
@@ -5,17 +5,16 @@ config = {
         'clobber',
         'build',
         'check-test',
 #        'update',
     ],
     'stage_platform': 'win64-add-on-devel',
     #### 64 bit build specific #####
     'env': {
-        'BINSCOPE': 'C:/Program Files (x86)/Microsoft/SDL BinScope/BinScope.exe',
         'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 'C:/mozilla-build/buildbotve/scripts;'
                 '%s' % (os.environ.get('path')),
         'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
         'TINDERBOX_OUTPUT': '1',
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/64_debug.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/64_debug.py
@@ -6,17 +6,16 @@ config = {
         'build',
         'check-test',
         'update',  # decided by query_is_nightly()
     ],
     'stage_platform': 'win64-debug',
     'debug_build': True,
     #### 64 bit build specific #####
     'env': {
-        'BINSCOPE': 'C:/Program Files (x86)/Microsoft/SDL BinScope/BinScope.exe',
         'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 'C:/mozilla-build/buildbotve/scripts;'
                 '%s' % (os.environ.get('path')),
         'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
         'TINDERBOX_OUTPUT': '1',
--- a/testing/mozharness/configs/builds/taskcluster_base_win32.py
+++ b/testing/mozharness/configs/builds/taskcluster_base_win32.py
@@ -1,17 +1,14 @@
 import os
 
 config = {
     'base_name': 'WINNT_5.2_%(branch)s',
     'platform': 'win32',
     'env': {
-        'BINSCOPE': os.path.join(
-            os.environ['ProgramFiles(x86)'], 'Microsoft', 'SDL BinScope', 'BinScope.exe'
-        ),
         'PDBSTR_PATH': 'C:/Program Files (x86)/Windows Kits/10/Debuggers/x86/srcsrv/pdbstr.exe',
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
         'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'mozconfig_platform': 'win32',
 }
--- a/testing/mozharness/configs/builds/taskcluster_base_windows.py
+++ b/testing/mozharness/configs/builds/taskcluster_base_windows.py
@@ -7,16 +7,19 @@ config = {
     ],
     'app_ini_path': '%(obj_dir)s/dist/bin/application.ini',
     # decides whether we want to use moz_sign_cmd in env
     'enable_signing': True,
     'vcs_share_base': os.path.join('y:', os.sep, 'hg-shared'),
     'max_build_output_timeout': 60 * 80,
 
     'env': {
+        'BINSCOPE': os.path.join(
+            os.environ['ProgramFiles'], 'Microsoft BinScope 2014', 'Binscope.exe'
+        ),
         'HG_SHARE_BASE_DIR': os.path.join('y:', os.sep, 'hg-shared'),
         'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
         'MOZ_CRASHREPORTER_NO_REPORT': '1',
         'MOZ_OBJDIR': '%(abs_obj_dir)s',
         'TINDERBOX_OUTPUT': '1',
         'TOOLTOOL_CACHE': 'c:/builds/tooltool_cache',
         'TOOLTOOL_HOME': '/c/builds',
         'MSYSTEM': 'MINGW32',
--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -1245,27 +1245,28 @@
         this.mStep = this.mInputElement.step;
         this.mIsPickerOpen = false;
 
         this.mResetButton =
           document.getAnonymousElementByAttribute(this, "anonid", "reset-button");
         this.mResetButton.style.visibility = "hidden";
 
         this.EVENTS.forEach((eventName) => {
-          this.addEventListener(eventName, this, { mozSystemGroup: true });
+          this.addEventListener(eventName, this, { mozSystemGroup: true }, false);
         });
         // Handle keypress separately since we need to catch it on capturing.
         this.addEventListener("keypress", this, {
           capture: true,
           mozSystemGroup: true
-        });
+        }, false);
         // This is to open the picker when input element is clicked (this
         // includes padding area).
         this.mInputElement.addEventListener("click", this,
-                                            { mozSystemGroup: true });
+                                            { mozSystemGroup: true },
+                                            false);
       ]]>
       </constructor>
 
       <destructor>
       <![CDATA[
         this.EVENTS.forEach((eventName) => {
           this.removeEventListener(eventName, this, { mozSystemGroup: true });
         });
--- a/widget/windows/WinCompositorWidget.cpp
+++ b/widget/windows/WinCompositorWidget.cpp
@@ -364,18 +364,16 @@ WinCompositorWidget::DestroyCompositorWi
   }
   WinCompositorWindowThread::DestroyCompositorWindow(mCompositorWnd);
   mCompositorWnd = nullptr;
 }
 
 void
 WinCompositorWidget::UpdateCompositorWndSizeIfNecessary()
 {
-  MOZ_ASSERT(mCompositorWnd);
-
   if (!mCompositorWnd) {
     return;
   }
 
   LayoutDeviceIntSize size = GetClientSize();
   if (mLastCompositorWndSize == size) {
     return;
   }