Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 01 Mar 2017 17:18:37 -0800
changeset 345359 e91de6fb2b3dce9c932428265b0fdb630ea470d7
parent 345280 e150eaff1f83e4e4a97d1e30c57d233859efe9cb (current diff)
parent 345358 f3b989e0a7b90950c47dd72425c7f669f027c685 (diff)
child 345490 20f706c6244a69638d90d14eb5b0ea7bd873942c
child 345547 c688b2234591df521e868c5938d63d63135ab272
push id31436
push userkwierso@gmail.com
push dateThu, 02 Mar 2017 01:18:52 +0000
treeherdermozilla-central@e91de6fb2b3d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
e91de6fb2b3d / 54.0a1 / 20170302110226 / files
nightly linux64
e91de6fb2b3d / 54.0a1 / 20170302110226 / files
nightly mac
e91de6fb2b3d / 54.0a1 / 20170302030206 / files
nightly win32
e91de6fb2b3d / 54.0a1 / 20170302030206 / files
nightly win64
e91de6fb2b3d / 54.0a1 / 20170302030206 / 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 central, a=merge MozReview-Commit-ID: 7vInHaD1geB
devtools/client/inspector/layout/actions/grids.js
devtools/client/inspector/layout/actions/highlighter-settings.js
devtools/client/inspector/layout/actions/index.js
devtools/client/inspector/layout/actions/moz.build
devtools/client/inspector/layout/components/Grid.js
devtools/client/inspector/layout/components/GridDisplaySettings.js
devtools/client/inspector/layout/components/GridItem.js
devtools/client/inspector/layout/components/GridList.js
devtools/client/inspector/layout/components/GridOutline.js
devtools/client/inspector/layout/reducers/grids.js
devtools/client/inspector/layout/reducers/highlighter-settings.js
devtools/client/inspector/layout/reducers/moz.build
devtools/client/inspector/layout/types.js
devtools/client/inspector/layout/utils/l10n.js
devtools/client/inspector/layout/utils/moz.build
dom/workers/test/serviceworkers/claim_fetch_worker.js
dom/workers/test/serviceworkers/test_claim_fetch.html
intl/unicharutil/util/internal/moz.build
intl/unicharutil/util/objs.mozbuild
media/mtransport/testlib/moz.build
netwerk/protocol/http/nsHttpPipeline.cpp
netwerk/protocol/http/nsHttpPipeline.h
netwerk/test/unit/test_assoc.js
rdf/util/internal/moz.build
rdf/util/moz.build
rdf/util/nsRDFResource.cpp
rdf/util/nsRDFResource.h
rdf/util/objs.mozbuild
security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.cc
security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.h
security/sandbox/chromium/sandbox/win/wow_helper/target_code.cc
security/sandbox/chromium/sandbox/win/wow_helper/target_code.h
security/sandbox/chromium/sandbox/win/wow_helper/wow_helper.cc
security/sandbox/win/wow_helper/Makefile.in
security/sandbox/win/wow_helper/moz.build
testing/web-platform/meta/fetch/api/policies/referrer-origin-service-worker.https.html.ini
testing/web-platform/meta/fetch/api/policies/referrer-origin-worker.html.ini
testing/web-platform/meta/fetch/api/policies/referrer-origin.html.ini
testing/web-platform/meta/fetch/api/request/request-init-001.sub.html.ini
toolkit/profile/nsProfileStringTypes.h
xpcom/string/nsEmbedString.h
xpfe/test/child-window.html
xpfe/test/winopen.js
xpfe/test/winopen.xul
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Touching clobber for Telemetry IPC refactor in bug 1339749.
+Touching clobber for Bug 1322703 - Use -Fd to specify unique PDB filename per-compile for MSVC
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -16,17 +16,16 @@
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
 
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
-#include "nsStringGlue.h"
 
 #ifdef XP_WIN
 #ifdef MOZ_ASAN
 // ASAN requires firefox.exe to be built with -MD, and it's OK if we don't
 // support Windows XP SP2 in ASAN builds.
 #define XRE_DONT_SUPPORT_XPSP2
 #endif
 #define XRE_WANT_ENVIRON
@@ -35,17 +34,17 @@
 #include "mozilla/sandboxing/SandboxInitialization.h"
 #endif
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Sprintf.h"
-#include "mozilla/Telemetry.h"
+#include "mozilla/StartupTimeline.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 #ifdef LIBFUZZER
 #include "FuzzerDefs.h"
 #endif
 
 #ifdef MOZ_LINUX_32_SSE2_STARTUP_ERROR
 #include <cpuid.h>
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -133,23 +133,16 @@ endif
 DEFINES += -DMOZ_ICU_DBG_SUFFIX=$(MOZ_ICU_DBG_SUFFIX)
 DEFINES += -DICU_DATA_FILE=$(ICU_DATA_FILE)
 ifdef CLANG_CXX
 DEFINES += -DCLANG_CXX
 endif
 ifdef CLANG_CL
 DEFINES += -DCLANG_CL
 endif
-ifeq (x86,$(CPU_ARCH))
-ifdef _MSC_VER
-ifndef CLANG_CL
-DEFINES += -DWOW_HELPER
-endif
-endif
-endif
 
 
 # Builds using the hybrid FasterMake/RecursiveMake backend will
 # fail to produce a langpack. See bug 1255096.
 libs::
 ifeq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
 	$(MAKE) -C $(DEPTH)/browser/locales langpack
 endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -722,24 +722,16 @@
 #endif
 @RESPATH@/chrome/pippki@JAREXT@
 @RESPATH@/chrome/pippki.manifest
 @RESPATH@/components/pipnss.xpt
 @RESPATH@/components/pippki.xpt
 
 ; For process sandboxing
 #if defined(MOZ_SANDBOX)
-#if defined(XP_WIN)
-#if defined(WOW_HELPER)
-@BINPATH@/wow_helper.exe
-#endif
-#endif
-#endif
-
-#if defined(MOZ_SANDBOX)
 #if defined(XP_LINUX)
 @BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
 @RESPATH@/components/sandbox.xpt
 #endif
 #endif
 
 ; for Solaris SPARC
 #ifdef SOLARIS
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -148,17 +148,32 @@ EMBED_MANIFEST_AT=2
 
 endif # MKSHLIB
 endif # FORCE_SHARED_LIB
 endif # LIBRARY
 
 ifeq ($(OS_ARCH),WINNT)
 ifndef GNU_CC
 
+#
+# Unless we're building SIMPLE_PROGRAMS, all C++ files share a PDB file per
+# directory. For parallel builds, this PDB file is shared and locked by
+# MSPDBSRV.EXE, starting with MSVC8 SP1. If you're using MSVC 7.1 or MSVC8
+# without SP1, don't do parallel builds.
+#
+# The final PDB for libraries and programs is created by the linker and uses
+# a different name from the single PDB file created by the compiler. See
+# bug 462740.
+#
+
+ifdef SIMPLE_PROGRAMS
 COMPILE_PDB_FLAG ?= -Fd$(basename $(@F)).pdb
+else
+COMPILE_PDB_FLAG ?= -Fdgenerated.pdb
+endif
 COMPILE_CFLAGS += $(COMPILE_PDB_FLAG)
 COMPILE_CXXFLAGS += $(COMPILE_PDB_FLAG)
 
 LINK_PDBFILE ?= $(basename $(@F)).pdb
 ifdef MOZ_DEBUG
 CODFILE=$(basename $(@F)).cod
 endif
 
rename from devtools/client/inspector/layout/actions/grids.js
rename to devtools/client/inspector/grids/actions/grids.js
rename from devtools/client/inspector/layout/actions/highlighter-settings.js
rename to devtools/client/inspector/grids/actions/highlighter-settings.js
rename from devtools/client/inspector/layout/actions/index.js
rename to devtools/client/inspector/grids/actions/index.js
rename from devtools/client/inspector/layout/actions/moz.build
rename to devtools/client/inspector/grids/actions/moz.build
rename from devtools/client/inspector/layout/components/Grid.js
rename to devtools/client/inspector/grids/components/Grid.js
--- a/devtools/client/inspector/layout/components/Grid.js
+++ b/devtools/client/inspector/grids/components/Grid.js
@@ -22,16 +22,17 @@ module.exports = createClass({
     getSwatchColorPickerTooltip: PropTypes.func.isRequired,
     grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
     highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
     setSelectedNode: PropTypes.func.isRequired,
     showGridOutline: PropTypes.bool.isRequired,
     onHideBoxModelHighlighter: PropTypes.func.isRequired,
     onSetGridOverlayColor: PropTypes.func.isRequired,
     onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
+    onShowGridAreaHighlight: PropTypes.func.isRequired,
     onToggleGridHighlighter: PropTypes.func.isRequired,
     onToggleShowGridLineNumbers: PropTypes.func.isRequired,
     onToggleShowInfiniteLines: PropTypes.func.isRequired,
   },
 
   mixins: [ addons.PureRenderMixin ],
 
   render() {
@@ -42,26 +43,28 @@ module.exports = createClass({
       setSelectedNode,
       showGridOutline,
       onHideBoxModelHighlighter,
       onSetGridOverlayColor,
       onShowBoxModelHighlighterForNode,
       onToggleGridHighlighter,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
+      onShowGridAreaHighlight,
     } = this.props;
 
     return grids.length ?
       dom.div(
         {
           id: "layout-grid-container",
         },
         showGridOutline ?
           GridOutline({
             grids,
+            onShowGridAreaHighlight,
           })
           :
           null,
         dom.div(
           {
             className: "grid-content",
           },
           GridList({
rename from devtools/client/inspector/layout/components/GridDisplaySettings.js
rename to devtools/client/inspector/grids/components/GridDisplaySettings.js
rename from devtools/client/inspector/layout/components/GridItem.js
rename to devtools/client/inspector/grids/components/GridItem.js
rename from devtools/client/inspector/layout/components/GridList.js
rename to devtools/client/inspector/grids/components/GridList.js
rename from devtools/client/inspector/layout/components/GridOutline.js
rename to devtools/client/inspector/grids/components/GridOutline.js
--- a/devtools/client/inspector/layout/components/GridOutline.js
+++ b/devtools/client/inspector/grids/components/GridOutline.js
@@ -18,98 +18,183 @@ const VIEWPORT_HEIGHT = 100;
 const VIEWPORT_WIDTH = 450;
 
 module.exports = createClass({
 
   displayName: "GridOutline",
 
   propTypes: {
     grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
+    onShowGridAreaHighlight: PropTypes.func.isRequired,
   },
 
   mixins: [ addons.PureRenderMixin ],
 
   getInitialState() {
     return {
       selectedGrids: [],
     };
   },
 
   componentWillReceiveProps({ grids }) {
     this.setState({
       selectedGrids: grids.filter(grid => grid.highlighted),
     });
   },
 
-  renderGridCell(columnNumber, rowNumber, color) {
-    return dom.rect(
-      {
-        className: "grid-outline-cell",
-        x: columnNumber,
-        y: rowNumber,
-        width: 10,
-        height: 10,
-        stroke: color,
-      }
+  /**
+   * Returns the grid area name if the given grid cell is part of a grid area, otherwise
+   * null.
+   *
+   * @param  {Number} columnNumber
+   *         The column number of the grid cell.
+   * @param  {Number} rowNumber
+   *         The row number of the grid cell.
+   * @param  {Array} areas
+   *         Array of grid areas data stored in the grid fragment.
+   * @return {String} If there is a grid area return area name, otherwise null.
+   */
+  getGridAreaName(columnNumber, rowNumber, areas) {
+    const gridArea = areas.find(area =>
+      (area.rowStart <= rowNumber && area.rowEnd > rowNumber) &&
+      (area.columnStart <= columnNumber && area.columnEnd > columnNumber)
     );
+
+    if (!gridArea) {
+      return null;
+    }
+
+    return gridArea.name;
   },
 
-  renderGridFragment({ color, gridFragments }) {
+  /**
+   * Renders the grid outline for the given grid container object.
+   *
+   * @param  {Object} grid
+   *         A single grid container in the document.
+   */
+  renderGrid(grid) {
+    const { id, color, gridFragments } = grid;
     // TODO: We are drawing the first fragment since only one is currently being stored.
-    // In future we will need to iterate over all fragments of a grid.
-    const { rows, cols } = gridFragments[0];
-    const numOfColLines = cols.lines.length - 1;
-    const numOfRowLines = rows.lines.length - 1;
+    // In the future we will need to iterate over all fragments of a grid.
+    const { rows, cols, areas } = gridFragments[0];
+    const numberOfColumns = cols.lines.length - 1;
+    const numberOfRows = rows.lines.length - 1;
     const rectangles = [];
 
-    // Draw a rectangle that acts as a border for the grid outline
-    const border = this.renderGridOutlineBorder(numOfRowLines, numOfColLines, color);
+    // Draw a rectangle that acts as a border for the grid outline.
+    const border = this.renderGridOutlineBorder(numberOfRows, numberOfColumns, color);
     rectangles.push(border);
 
     let x = 1;
     let y = 1;
     const width = 10;
     const height = 10;
 
-    // Draw the cells within the grid outline border
-    for (let row = 0; row < numOfRowLines; row++) {
-      for (let col = 0; col < numOfColLines; col++) {
-        rectangles.push(this.renderGridCell(x, y, color));
+    // Draw the cells within the grid outline border.
+    for (let rowNumber = 1; rowNumber <= numberOfRows; rowNumber++) {
+      for (let columnNumber = 1; columnNumber <= numberOfColumns; columnNumber++) {
+        const gridAreaName = this.getGridAreaName(columnNumber, rowNumber, areas);
+        const gridCell = this.renderGridCell(id, x, y, rowNumber, columnNumber, color,
+          gridAreaName);
+
+        rectangles.push(gridCell);
         x += width;
       }
 
       x = 1;
       y += height;
     }
 
     return rectangles;
   },
 
-  renderGridOutline(gridFragments) {
+  /**
+   * Renders the grid cell of a grid fragment.
+   *
+   * @param  {Number} id
+   *         The grid id stored on the grid fragment
+   * @param  {Number} x
+   *         The x-position of the grid cell.
+   * @param  {Number} y
+   *         The y-position of the grid cell.
+   * @param  {Number} rowNumber
+   *         The row number of the grid cell.
+   * @param  {Number} columnNumber
+   *         The column number of the grid cell.
+   * @param  {String|null} gridAreaName
+   *         The grid area name or null if the grid cell is not part of a grid area.
+   */
+  renderGridCell(id, x, y, rowNumber, columnNumber, color, gridAreaName) {
+    return dom.rect(
+      {
+        className: "grid-outline-cell",
+        "data-grid-area-name": gridAreaName,
+        "data-grid-id": id,
+        x,
+        y,
+        width: 10,
+        height: 10,
+        fill: "none",
+        stroke: color,
+        onMouseOver: this.onMouseOverCell,
+        onMouseOut: this.onMouseLeaveCell,
+      }
+    );
+  },
+
+  renderGridOutline(grids) {
     return dom.g(
       {
         className: "grid-cell-group",
       },
-      gridFragments.map(gridFragment => this.renderGridFragment(gridFragment))
+      grids.map(grid => this.renderGrid(grid))
     );
   },
 
-  renderGridOutlineBorder(numberOfRows, numberOfCols, color) {
+  renderGridOutlineBorder(numberOfRows, numberOfColumns, color) {
     return dom.rect(
       {
         className: "grid-outline-border",
         x: 1,
         y: 1,
-        width: numberOfCols * 10,
+        width: numberOfColumns * 10,
         height: numberOfRows * 10,
         stroke: color,
       }
     );
   },
 
+  onMouseLeaveCell({ target }) {
+    const {
+      grids,
+      onShowGridAreaHighlight,
+    } = this.props;
+    const id = target.getAttribute("data-grid-id");
+    const color = target.getAttribute("stroke");
+
+    target.setAttribute("fill", "none");
+
+    onShowGridAreaHighlight(grids[id].nodeFront, null, color);
+  },
+
+  onMouseOverCell({ target }) {
+    const {
+      grids,
+      onShowGridAreaHighlight,
+    } = this.props;
+    const name = target.getAttribute("data-grid-area-name");
+    const id = target.getAttribute("data-grid-id");
+    const color = target.getAttribute("stroke");
+
+    target.setAttribute("fill", color);
+
+    onShowGridAreaHighlight(grids[id].nodeFront, name, color);
+  },
+
   render() {
     return this.state.selectedGrids.length ?
       dom.svg(
         {
           className: "grid-outline",
           width: "100%",
           height: 100,
           viewBox: `${TRANSLATE_X} ${TRANSLATE_Y} ${VIEWPORT_WIDTH} ${VIEWPORT_HEIGHT}`,
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/components/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=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/.
+
+DevToolsModules(
+    'Grid.js',
+    'GridDisplaySettings.js',
+    'GridItem.js',
+    'GridList.js',
+    'GridOutline.js',
+)
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -0,0 +1,404 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Services = require("Services");
+const { Task } = require("devtools/shared/task");
+
+const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
+
+const {
+  updateGridColor,
+  updateGridHighlighted,
+  updateGrids,
+} = require("./actions/grids");
+const {
+  updateShowGridLineNumbers,
+  updateShowInfiniteLines,
+} = require("./actions/highlighter-settings");
+
+const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
+const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
+
+// Default grid colors.
+const GRID_COLORS = [
+  "#05E4EE",
+  "#BB9DFF",
+  "#FFB53B",
+  "#71F362",
+  "#FF90FF",
+  "#FF90FF",
+  "#1B80FF",
+  "#FF2647"
+];
+
+function GridInspector(inspector, window) {
+  this.document = window.document;
+  this.highlighters = inspector.highlighters;
+  this.inspector = inspector;
+  this.store = inspector.store;
+  this.walker = this.inspector.walker;
+
+  this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
+  this.setSelectedNode = this.setSelectedNode.bind(this);
+  this.updateGridPanel = this.updateGridPanel.bind(this);
+
+  this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
+  this.onHighlighterChange = this.onHighlighterChange.bind(this);
+  this.onSetGridOverlayColor = this.onSetGridOverlayColor.bind(this);
+  this.onShowBoxModelHighlighterForNode =
+    this.onShowBoxModelHighlighterForNode.bind(this);
+  this.onShowGridAreaHighlight = this.onShowGridAreaHighlight.bind(this);
+  this.onSidebarSelect = this.onSidebarSelect.bind(this);
+  this.onToggleGridHighlighter = this.onToggleGridHighlighter.bind(this);
+  this.onToggleShowGridLineNumbers = this.onToggleShowGridLineNumbers.bind(this);
+  this.onToggleShowInfiniteLines = this.onToggleShowInfiniteLines.bind(this);
+
+  this.init();
+}
+
+GridInspector.prototype = {
+
+  /**
+   * Initializes the grid inspector by fetching the LayoutFront from the walker, loading
+   * the highlighter settings and initalizing the SwatchColorPicker instance.
+   */
+  init: Task.async(function* () {
+    if (!this.inspector) {
+      return;
+    }
+
+    this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
+
+    this.loadHighlighterSettings();
+
+    // Create a shared SwatchColorPicker instance to be reused by all GridItem components.
+    this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
+      this.inspector.toolbox.doc,
+      this.inspector,
+      {
+        supportsCssColor4ColorFunction: () => false
+      }
+    );
+
+    this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
+    this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
+    this.inspector.sidebar.on("select", this.onSidebarSelect);
+
+    this.onSidebarSelect();
+  }),
+
+  /**
+   * Destruction function called when the inspector is destroyed. Removes event listeners
+   * and cleans up references.
+   */
+  destroy() {
+    this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
+    this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
+    this.inspector.sidebar.off("select", this.onSidebarSelect);
+    this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
+
+    this.swatchColorPickerTooltip.destroy();
+
+    this.document = null;
+    this.highlighters = null;
+    this.inspector = null;
+    this.layoutInspector = null;
+    this.store = null;
+    this.swatchColorPickerTooltip = null;
+    this.walker = null;
+  },
+
+  getComponentProps() {
+    return {
+      getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
+      setSelectedNode: this.setSelectedNode,
+      onSetGridOverlayColor: this.onSetGridOverlayColor,
+      onShowBoxModelHighlighterForNode: this.onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight: this.onShowGridAreaHighlight,
+      onToggleGridHighlighter: this.onToggleGridHighlighter,
+      onToggleShowGridLineNumbers: this.onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines: this.onToggleShowInfiniteLines,
+    };
+  },
+
+  /**
+   * Returns the color set for the grid highlighter associated with the provided
+   * nodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront for which we need the color.
+   */
+  getGridColorForNodeFront(nodeFront) {
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.nodeFront === nodeFront) {
+        return grid.color;
+      }
+    }
+
+    return null;
+  },
+
+  /**
+   * Create a highlighter settings object for the provided nodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront for which we need highlighter settings.
+   */
+  getGridHighlighterSettings(nodeFront) {
+    let { highlighterSettings } = this.store.getState();
+
+    // Get the grid color for the provided nodeFront.
+    let color = this.getGridColorForNodeFront(nodeFront);
+
+    // Merge the grid color to the generic highlighter settings.
+    return Object.assign({}, highlighterSettings, {
+      color
+    });
+  },
+
+  /**
+   * Retrieve the shared SwatchColorPicker instance.
+   */
+  getSwatchColorPickerTooltip() {
+    return this.swatchColorPickerTooltip;
+  },
+
+  /**
+   * Returns true if the layout panel is visible, and false otherwise.
+   */
+  isPanelVisible() {
+    return this.inspector.toolbox.currentToolId === "inspector" &&
+           this.inspector.sidebar &&
+           this.inspector.sidebar.getCurrentTabID() === "layoutview";
+  },
+
+  /**
+   * Load the grid highligher display settings into the store from the stored preferences.
+   */
+  loadHighlighterSettings() {
+    let { dispatch } = this.store;
+
+    let showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
+    let showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
+
+    dispatch(updateShowGridLineNumbers(showGridLineNumbers));
+    dispatch(updateShowInfiniteLines(showInfinteLines));
+  },
+
+  /**
+   * Set the inspector selection.
+   *
+   * @param {NodeFront} nodeFront
+   *        The NodeFront corresponding to the new selection.
+   */
+  setSelectedNode(nodeFront) {
+    this.inspector.selection.setNodeFront(nodeFront, "layout-panel");
+  },
+
+  /**
+   * Updates the grid panel by dispatching the new grid data. This is called when the
+   * layout view becomes visible or the view needs to be updated with new grid data.
+   *
+   * @param  {Array|null} gridFronts
+   *         Optional array of all GridFront in the current page.
+   */
+  updateGridPanel: Task.async(function* (gridFronts) {
+    // Stop refreshing if the inspector or store is already destroyed.
+    if (!this.inspector || !this.store) {
+      return;
+    }
+
+    // Get all the GridFront from the server if no gridFronts were provided.
+    if (!gridFronts) {
+      gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
+    }
+
+    let grids = [];
+    for (let i = 0; i < gridFronts.length; i++) {
+      let grid = gridFronts[i];
+      let nodeFront = yield this.walker.getNodeFromActor(grid.actorID, ["containerEl"]);
+
+      let fallbackColor = GRID_COLORS[i % GRID_COLORS.length];
+      let color = this.getGridColorForNodeFront(nodeFront) || fallbackColor;
+
+      grids.push({
+        id: i,
+        color,
+        gridFragments: grid.gridFragments,
+        highlighted: nodeFront == this.highlighters.gridHighlighterShown,
+        nodeFront,
+      });
+    }
+
+    this.store.dispatch(updateGrids(grids));
+  }),
+
+  /**
+   * Handler for "grid-layout-changed" events emitted from the LayoutActor.
+   *
+   * @param  {Array} grids
+   *         Array of all GridFront in the current page.
+   */
+  onGridLayoutChange(grids) {
+    if (this.isPanelVisible()) {
+      this.updateGridPanel(grids);
+    }
+  },
+
+  /**
+   * Handler for "grid-highlighter-shown" and "grid-highlighter-hidden" events emitted
+   * from the HighlightersOverlay. Updates the NodeFront's grid highlighted state.
+   *
+   * @param  {Event} event
+   *         Event that was triggered.
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront of the grid container element for which the grid highlighter
+   *         is shown for.
+   */
+  onHighlighterChange(event, nodeFront) {
+    let highlighted = event === "grid-highlighter-shown";
+    this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
+  },
+
+  /**
+   * Handler for a change in the grid overlay color picker for a grid container.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid color is
+   *         being updated.
+   * @param  {String} color
+   *         A hex string representing the color to use.
+   */
+  onSetGridOverlayColor(node, color) {
+    this.store.dispatch(updateGridColor(node, color));
+    let { grids } = this.store.getState();
+
+    // If the grid for which the color was updated currently has a highlighter, update
+    // the color.
+    for (let grid of grids) {
+      if (grid.nodeFront === node && grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(node);
+        this.highlighters.showGridHighlighter(node, highlighterSettings);
+      }
+    }
+  },
+
+  /**
+   * Shows the box-model highlighter on the element corresponding to the provided
+   * NodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The node to highlight.
+   * @param  {Object} options
+   *         Options passed to the highlighter actor.
+   */
+  onShowBoxModelHighlighterForNode(nodeFront, options) {
+    let toolbox = this.inspector.toolbox;
+    toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
+  },
+
+  /**
+   * Highlights the grid area in the CSS Grid Highlighter for the given grid.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid
+   *         highlighter is highlighted for.
+   * @param  {String} gridAreaName
+   *         The name of the grid area for which the grid highlighter
+   *         is highlighted for.
+   * @param  {String} color
+   *         The color of the grid area for which the grid highlighter
+   *         is highlighted for.
+   */
+  onShowGridAreaHighlight(node, gridAreaName, color) {
+    let { highlighterSettings } = this.store.getState();
+
+    highlighterSettings.showGridArea = gridAreaName;
+    highlighterSettings.color = color;
+
+    this.highlighters.showGridHighlighter(node, highlighterSettings);
+  },
+
+  /**
+   * Handler for the inspector sidebar select event. Starts listening for
+   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
+   * listening for grid layout changes. Finally, refresh the layout view if
+   * it is visible.
+   */
+  onSidebarSelect() {
+    if (!this.isPanelVisible()) {
+      this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
+      return;
+    }
+
+    this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
+    this.updateGridPanel();
+  },
+
+  /**
+   * Handler for a change in the input checkboxes in the GridList component.
+   * Toggles on/off the grid highlighter for the provided grid container element.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid
+   *         highlighter is toggled on/off for.
+   */
+  onToggleGridHighlighter(node) {
+    let highlighterSettings = this.getGridHighlighterSettings(node);
+    this.highlighters.toggleGridHighlighter(node, highlighterSettings);
+  },
+
+  /**
+   * Handler for a change in the show grid line numbers checkbox in the
+   * GridDisplaySettings component. Toggles on/off the option to show the grid line
+   * numbers in the grid highlighter. Refreshes the shown grid highlighter for the
+   * grids currently highlighted.
+   *
+   * @param  {Boolean} enabled
+   *         Whether or not the grid highlighter should show the grid line numbers.
+   */
+  onToggleShowGridLineNumbers(enabled) {
+    this.store.dispatch(updateShowGridLineNumbers(enabled));
+    Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
+
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
+        this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
+      }
+    }
+  },
+
+  /**
+   * Handler for a change in the extend grid lines infinitely checkbox in the
+   * GridDisplaySettings component. Toggles on/off the option to extend the grid
+   * lines infinitely in the grid highlighter. Refreshes the shown grid highlighter
+   * for grids currently highlighted.
+   *
+   * @param  {Boolean} enabled
+   *         Whether or not the grid highlighter should extend grid lines infinitely.
+   */
+  onToggleShowInfiniteLines(enabled) {
+    this.store.dispatch(updateShowInfiniteLines(enabled));
+    Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
+
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
+        this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
+      }
+    }
+  },
+
+};
+
+module.exports = GridInspector;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/moz.build
@@ -0,0 +1,17 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=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/.
+
+DIRS += [
+    'actions',
+    'components',
+    'reducers',
+    'utils',
+]
+
+DevToolsModules(
+    'grid-inspector.js',
+    'types.js',
+)
rename from devtools/client/inspector/layout/reducers/grids.js
rename to devtools/client/inspector/grids/reducers/grids.js
rename from devtools/client/inspector/layout/reducers/highlighter-settings.js
rename to devtools/client/inspector/grids/reducers/highlighter-settings.js
rename from devtools/client/inspector/layout/reducers/moz.build
rename to devtools/client/inspector/grids/reducers/moz.build
rename from devtools/client/inspector/layout/types.js
rename to devtools/client/inspector/grids/types.js
rename from devtools/client/inspector/layout/utils/l10n.js
rename to devtools/client/inspector/grids/utils/l10n.js
rename from devtools/client/inspector/layout/utils/moz.build
rename to devtools/client/inspector/grids/utils/moz.build
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -20,16 +20,17 @@ const nodeConstants = require("devtools/
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
 const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
 const BoxModel = require("devtools/client/inspector/boxmodel/box-model");
 const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
+const GridInspector = require("devtools/client/inspector/grids/grid-inspector");
 const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
 const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
 const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
 const MarkupView = require("devtools/client/inspector/markup/markup");
 const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
@@ -572,16 +573,18 @@ Inspector.prototype = {
     this.ruleview = new RuleViewTool(this, this.panelWin);
     this.boxmodel = new BoxModel(this, this.panelWin);
 
     const {ComputedViewTool} =
       this.browserRequire("devtools/client/inspector/computed/computed");
     this.computedview = new ComputedViewTool(this, this.panelWin);
 
     if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
+      this.gridInspector = new GridInspector(this, this.panelWin);
+
       const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
       this.layoutview = new LayoutView(this, this.panelWin);
     }
 
     if (this.target.form.animationsActor) {
       this.sidebar.addFrameTab(
         "animationinspector",
         INSPECTOR_L10N.getStr("inspector.sidebar.animationInspectorTitle"),
--- a/devtools/client/inspector/layout/components/App.js
+++ b/devtools/client/inspector/layout/components/App.js
@@ -5,36 +5,39 @@
 "use strict";
 
 const { addons, createClass, createFactory, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 
-const Accordion = createFactory(require("./Accordion"));
-const Grid = createFactory(require("./Grid"));
+const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
+const Grid = createFactory(require("devtools/client/inspector/grids/components/Grid"));
 
-const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
+const BoxModelTypes = require("devtools/client/inspector/boxmodel/types");
+const GridTypes = require("devtools/client/inspector/grids/types");
 
-const Types = require("../types");
-const { getStr } = require("../utils/l10n");
+const Accordion = createFactory(require("./Accordion"));
 
 const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
 const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
 
+const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
+const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
+
 const App = createClass({
 
   displayName: "App",
 
   propTypes: {
-    boxModel: PropTypes.shape(Types.boxModel).isRequired,
+    boxModel: PropTypes.shape(BoxModelTypes.boxModel).isRequired,
     getSwatchColorPickerTooltip: PropTypes.func.isRequired,
-    grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
-    highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
+    grids: PropTypes.arrayOf(PropTypes.shape(GridTypes.grid)).isRequired,
+    highlighterSettings: PropTypes.shape(GridTypes.highlighterSettings).isRequired,
     setSelectedNode: PropTypes.func.isRequired,
     showBoxModelProperties: PropTypes.bool.isRequired,
     showGridOutline: PropTypes.bool.isRequired,
     onHideBoxModelHighlighter: PropTypes.func.isRequired,
     onSetGridOverlayColor: PropTypes.func.isRequired,
     onShowBoxModelEditor: PropTypes.func.isRequired,
     onShowBoxModelHighlighter: PropTypes.func.isRequired,
     onToggleGridHighlighter: PropTypes.func.isRequired,
@@ -53,17 +56,17 @@ const App = createClass({
         items: [
           {
             header: BOXMODEL_L10N.getStr("boxmodel.title"),
             component: BoxModel,
             componentProps: this.props,
             opened: true,
           },
           {
-            header: getStr("layout.header"),
+            header: LAYOUT_L10N.getStr("layout.header"),
             component: Grid,
             componentProps: this.props,
             opened: true,
           },
         ]
       })
     );
   },
--- a/devtools/client/inspector/layout/components/moz.build
+++ b/devtools/client/inspector/layout/components/moz.build
@@ -3,14 +3,9 @@
 # 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/.
 
 DevToolsModules(
     'Accordion.css',
     'Accordion.js',
     'App.js',
-    'Grid.js',
-    'GridDisplaySettings.js',
-    'GridItem.js',
-    'GridList.js',
-    'GridOutline.js',
 )
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -1,231 +1,83 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Services = require("Services");
-const { Task } = require("devtools/shared/task");
 
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
-const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
-
-const {
-  updateGridColor,
-  updateGridHighlighted,
-  updateGrids,
-} = require("./actions/grids");
-const {
-  updateShowGridLineNumbers,
-  updateShowInfiniteLines,
-} = require("./actions/highlighter-settings");
-
 const App = createFactory(require("./components/App"));
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
   new LocalizationHelper("devtools/client/locales/inspector.properties");
 
-const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
 const SHOW_GRID_OUTLINE_PREF = "devtools.gridinspector.showGridOutline";
-const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
-
-// Default grid colors.
-const GRID_COLORS = [
-  "#05E4EE",
-  "#BB9DFF",
-  "#FFB53B",
-  "#71F362",
-  "#FF90FF",
-  "#FF90FF",
-  "#1B80FF",
-  "#FF2647"
-];
 
 function LayoutView(inspector, window) {
   this.document = window.document;
-  this.highlighters = inspector.highlighters;
   this.inspector = inspector;
   this.store = inspector.store;
-  this.walker = this.inspector.walker;
-
-  this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
-  this.onHighlighterChange = this.onHighlighterChange.bind(this);
-  this.onSidebarSelect = this.onSidebarSelect.bind(this);
 
   this.init();
 }
 
 LayoutView.prototype = {
 
-  /**
-   * Initializes the layout view by fetching the LayoutFront from the walker, creating
-   * the redux store and adding the view into the inspector sidebar.
-   */
-  init: Task.async(function* () {
+  init() {
     if (!this.inspector) {
       return;
     }
 
     let {
       onHideBoxModelHighlighter,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
     } = this.inspector.boxmodel.getComponentProps();
 
-    this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
-
-    this.loadHighlighterSettings();
-
-    this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
-    this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
-    this.inspector.sidebar.on("select", this.onSidebarSelect);
-
-    // Create a shared SwatchColorPicker instance to be reused by all GridItem components.
-    this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
-      this.inspector.toolbox.doc,
-      this.inspector,
-      {
-        supportsCssColor4ColorFunction: () => false
-      }
-    );
+    let {
+      getSwatchColorPickerTooltip,
+      setSelectedNode,
+      onSetGridOverlayColor,
+      onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight,
+      onToggleGridHighlighter,
+      onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines,
+    } = this.inspector.gridInspector.getComponentProps();
 
     let app = App({
-      /**
-       * Retrieve the shared SwatchColorPicker instance.
-       */
-      getSwatchColorPickerTooltip: () => {
-        return this.swatchColorPickerTooltip;
-      },
-
-      /**
-       * Set the inspector selection.
-       * @param {NodeFront} nodeFront
-       *        The NodeFront corresponding to the new selection.
-       */
-      setSelectedNode: (nodeFront) => {
-        this.inspector.selection.setNodeFront(nodeFront, "layout-panel");
-      },
-
+      getSwatchColorPickerTooltip,
+      setSelectedNode,
       /**
        * Shows the box model properties under the box model if true, otherwise, hidden by
        * default.
        */
       showBoxModelProperties: true,
 
       /**
        * Shows the grid outline if user preferences are set to true, otherwise, hidden by
        * default.
        */
       showGridOutline: Services.prefs.getBoolPref(SHOW_GRID_OUTLINE_PREF),
 
       onHideBoxModelHighlighter,
-
-      /**
-       * Handler for a change in the grid overlay color picker for a grid container.
-       *
-       * @param  {NodeFront} node
-       *         The NodeFront of the grid container element for which the grid color is
-       *         being updated.
-       * @param  {String} color
-       *         A hex string representing the color to use.
-       */
-      onSetGridOverlayColor: (node, color) => {
-        this.store.dispatch(updateGridColor(node, color));
-        let { grids } = this.store.getState();
-
-        // If the grid for which the color was updated currently has a highlighter, update
-        // the color.
-        for (let grid of grids) {
-          if (grid.nodeFront === node && grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(node);
-            this.highlighters.showGridHighlighter(node, highlighterSettings);
-          }
-        }
-      },
-
+      onSetGridOverlayColor,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
-
-     /**
-       * Shows the box-model highlighter on the element corresponding to the provided
-       * NodeFront.
-       *
-       * @param  {NodeFront} nodeFront
-       *         The node to highlight.
-       * @param  {Object} options
-       *         Options passed to the highlighter actor.
-       */
-      onShowBoxModelHighlighterForNode: (nodeFront, options) => {
-        let toolbox = this.inspector.toolbox;
-        toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
-      },
-
-      /**
-       * Handler for a change in the input checkboxes in the GridList component.
-       * Toggles on/off the grid highlighter for the provided grid container element.
-       *
-       * @param  {NodeFront} node
-       *         The NodeFront of the grid container element for which the grid
-       *         highlighter is toggled on/off for.
-       */
-      onToggleGridHighlighter: node => {
-        let highlighterSettings = this.getGridHighlighterSettings(node);
-        this.highlighters.toggleGridHighlighter(node, highlighterSettings);
-      },
-
-      /**
-       * Handler for a change in the show grid line numbers checkbox in the
-       * GridDisplaySettings component. Toggles on/off the option to show the grid line
-       * numbers in the grid highlighter. Refreshes the shown grid highlighter for the
-       * grids currently highlighted.
-       *
-       * @param  {Boolean} enabled
-       *         Whether or not the grid highlighter should show the grid line numbers.
-       */
-      onToggleShowGridLineNumbers: enabled => {
-        this.store.dispatch(updateShowGridLineNumbers(enabled));
-        Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
-
-        let { grids } = this.store.getState();
-
-        for (let grid of grids) {
-          if (grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
-            this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
-          }
-        }
-      },
-
-      /**
-       * Handler for a change in the extend grid lines infinitely checkbox in the
-       * GridDisplaySettings component. Toggles on/off the option to extend the grid
-       * lines infinitely in the grid highlighter. Refreshes the shown grid highlighter
-       * for grids currently highlighted.
-       *
-       * @param  {Boolean} enabled
-       *         Whether or not the grid highlighter should extend grid lines infinitely.
-       */
-      onToggleShowInfiniteLines: enabled => {
-        this.store.dispatch(updateShowInfiniteLines(enabled));
-        Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
-
-        let { grids } = this.store.getState();
-
-        for (let grid of grids) {
-          if (grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
-            this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
-          }
-        }
-      }
+      onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight,
+      onToggleGridHighlighter,
+      onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines,
     });
 
     let provider = createElement(Provider, {
       store: this.store,
       id: "layoutview",
       title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
       key: "layoutview",
     }, app);
@@ -233,170 +85,22 @@ LayoutView.prototype = {
     let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
 
     this.inspector.addSidebarTab(
       "layoutview",
       INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
       provider,
       defaultTab == "layoutview"
     );
-  }),
-
-  /**
-   * Destruction function called when the inspector is destroyed. Removes event listeners
-   * and cleans up references.
-   */
-  destroy() {
-    this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
-    this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
-    this.inspector.sidebar.off("select", this.onSidebarSelect);
-    this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
-
-    this.document = null;
-    this.inspector = null;
-    this.layoutInspector = null;
-    this.store = null;
-    this.walker = null;
-  },
-
-  /**
-   * Returns the color set for the grid highlighter associated with the provided
-   * nodeFront.
-   *
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront for which we need the color.
-   */
-  getGridColorForNodeFront(nodeFront) {
-    let { grids } = this.store.getState();
-
-    for (let grid of grids) {
-      if (grid.nodeFront === nodeFront) {
-        return grid.color;
-      }
-    }
-
-    return null;
-  },
-
-  /**
-   * Create a highlighter settings object for the provided nodeFront.
-   *
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront for which we need highlighter settings.
-   */
-  getGridHighlighterSettings(nodeFront) {
-    let { highlighterSettings } = this.store.getState();
-
-    // Get the grid color for the provided nodeFront.
-    let color = this.getGridColorForNodeFront(nodeFront);
-
-    // Merge the grid color to the generic highlighter settings.
-    return Object.assign({}, highlighterSettings, {
-      color
-    });
-  },
-
-  /**
-   * Returns true if the layout panel is visible, and false otherwise.
-   */
-  isPanelVisible() {
-    return this.inspector.toolbox.currentToolId === "inspector" &&
-           this.inspector.sidebar &&
-           this.inspector.sidebar.getCurrentTabID() === "layoutview";
-  },
-
-  /**
-   * Load the grid highligher display settings into the store from the stored preferences.
-   */
-  loadHighlighterSettings() {
-    let { dispatch } = this.store;
-
-    let showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
-    let showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
-
-    dispatch(updateShowGridLineNumbers(showGridLineNumbers));
-    dispatch(updateShowInfiniteLines(showInfinteLines));
   },
 
   /**
-   * Updates the grid panel by dispatching the new grid data. This is called when the
-   * layout view becomes visible or the view needs to be updated with new grid data.
-   *
-   * @param {Array|null} gridFronts
-   *        Optional array of all GridFront in the current page.
+   * Destruction function called when the inspector is destroyed. Cleans up references.
    */
-  updateGridPanel: Task.async(function* (gridFronts) {
-    // Stop refreshing if the inspector or store is already destroyed.
-    if (!this.inspector || !this.store) {
-      return;
-    }
-
-    // Get all the GridFront from the server if no gridFronts were provided.
-    if (!gridFronts) {
-      gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
-    }
-
-    let grids = [];
-    for (let i = 0; i < gridFronts.length; i++) {
-      let grid = gridFronts[i];
-      let nodeFront = yield this.walker.getNodeFromActor(grid.actorID, ["containerEl"]);
-
-      let fallbackColor = GRID_COLORS[i % GRID_COLORS.length];
-      let color = this.getGridColorForNodeFront(nodeFront) || fallbackColor;
-
-      grids.push({
-        id: i,
-        color,
-        gridFragments: grid.gridFragments,
-        highlighted: nodeFront == this.highlighters.gridHighlighterShown,
-        nodeFront,
-      });
-    }
-
-    this.store.dispatch(updateGrids(grids));
-  }),
-
-  /**
-   * Handler for "grid-layout-changed" events emitted from the LayoutActor.
-   *
-   * @param  {Array} grids
-   *         Array of all GridFront in the current page.
-   */
-  onGridLayoutChange(grids) {
-    if (this.isPanelVisible()) {
-      this.updateGridPanel(grids);
-    }
-  },
-
-  /**
-   * Handler for "grid-highlighter-shown" and "grid-highlighter-hidden" events emitted
-   * from the HighlightersOverlay. Updates the NodeFront's grid highlighted state.
-   *
-   * @param  {Event} event
-   *         Event that was triggered.
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront of the grid container element for which the grid highlighter
-   *         is shown for.
-   */
-  onHighlighterChange(event, nodeFront) {
-    let highlighted = event === "grid-highlighter-shown";
-    this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
-  },
-
-  /**
-   * Handler for the inspector sidebar select event. Starts listening for
-   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
-   * listening for grid layout changes. Finally, refresh the layout view if
-   * it is visible.
-   */
-  onSidebarSelect() {
-    if (!this.isPanelVisible()) {
-      this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
-      return;
-    }
-
-    this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
-    this.updateGridPanel();
+  destroy() {
+    this.document = null;
+    this.inspector = null;
+    this.store = null;
   },
 
 };
 
 module.exports = LayoutView;
--- a/devtools/client/inspector/layout/moz.build
+++ b/devtools/client/inspector/layout/moz.build
@@ -1,17 +1,13 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
 DIRS += [
-    'actions',
     'components',
-    'reducers',
-    'utils',
 ]
 
 DevToolsModules(
     'layout.js',
-    'types.js',
 )
--- a/devtools/client/inspector/moz.build
+++ b/devtools/client/inspector/moz.build
@@ -2,16 +2,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'boxmodel',
     'components',
     'computed',
     'fonts',
+    'grids',
     'layout',
     'markup',
     'rules',
     'shared'
 ]
 
 DevToolsModules(
     'breadcrumbs.js',
--- a/devtools/client/inspector/reducers.js
+++ b/devtools/client/inspector/reducers.js
@@ -3,10 +3,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // This file exposes the Redux reducers of the box model, grid and grid highlighter
 // settings.
 
 exports.boxModel = require("devtools/client/inspector/boxmodel/reducers/box-model");
-exports.grids = require("devtools/client/inspector/layout/reducers/grids");
-exports.highlighterSettings = require("devtools/client/inspector/layout/reducers/highlighter-settings");
+exports.grids = require("devtools/client/inspector/grids/reducers/grids");
+exports.highlighterSettings = require("devtools/client/inspector/grids/reducers/highlighter-settings");
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -9,16 +9,17 @@ const { devtools } = Cu.import("resource
 const { joinURI } = devtools.require("devtools/shared/path");
 const { assert } = devtools.require("devtools/shared/DevToolsUtils");
 const Services = devtools.require("Services");
 const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
 
 const BROWSER_BASED_DIRS = [
   "resource://devtools/client/inspector/boxmodel",
   "resource://devtools/client/inspector/computed",
+  "resource://devtools/client/inspector/grids",
   "resource://devtools/client/inspector/layout",
   "resource://devtools/client/jsonview",
   "resource://devtools/client/shared/vendor",
   "resource://devtools/client/shared/redux",
 ];
 
 const COMMON_LIBRARY_DIRS = [
   "resource://devtools/client/shared/vendor",
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -62,21 +62,24 @@
 }
 
 .grid-outline-border {
   stroke-width: 0.75;
   fill: none;
 }
 
 .grid-outline-cell {
-  fill: none;
   pointer-events: all;
   stroke-dasharray: 0.5, 2;
 }
 
+.grid-outline-cell:hover {
+  opacity: 0.45;
+}
+
 /**
  * Container when no grids are present
  */
 
 .layout-no-grids {
   font-style: italic;
   text-align: center;
   padding: 0.5em;
--- a/devtools/server/actors/highlighters.css
+++ b/devtools/server/actors/highlighters.css
@@ -225,23 +225,25 @@
   left: 0;
   image-rendering: -moz-crisp-edges;
 }
 
 :-moz-native-anonymous .css-grid-regions {
   opacity: 0.6;
 }
 
-:-moz-native-anonymous .css-grid-areas {
+:-moz-native-anonymous .css-grid-areas,
+:-moz-native-anonymous .css-grid-cells {
   fill: #CEC0ED;
   stroke: none;
 }
 
-:-moz-native-anonymous .css-grid-infobar-areaname {
-  color: hsl(285,100%, 75%);
+:-moz-native-anonymous .css-grid-area-infobar-name,
+:-moz-native-anonymous .css-grid-cell-infobar-position {
+  color: hsl(285, 100%, 75%);
 }
 
 /* CSS Transform Highlighter */
 
 :-moz-native-anonymous .css-transform-transformed {
   fill: var(--highlighter-content-color);
   opacity: 0.8;
 }
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -16,19 +16,21 @@ const {
 const {
   getCurrentZoom,
   setIgnoreLayoutChanges,
   getWindowDimensions
 } = require("devtools/shared/layout/utils");
 const { stringifyGridFragments } = require("devtools/server/actors/utils/css-grid-utils");
 
 const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
+
 const DEFAULT_GRID_COLOR = "#4B0082";
+
+const COLUMNS = "cols";
 const ROWS = "rows";
-const COLUMNS = "cols";
 
 const GRID_LINES_PROPERTIES = {
   "edge": {
     lineDash: [0, 0],
     alpha: 1,
   },
   "explicit": {
     lineDash: [5, 3],
@@ -64,41 +66,56 @@ const COLUMN_KEY = {};
  * h.show(node, options);
  * h.hide();
  * h.destroy();
  *
  * Available Options:
  * - color(colorValue)
  *     @param  {String} colorValue
  *     The color that should be used to draw the highlighter for this grid.
+ * - showAllGridAreas(isShown)
+ *     @param  {Boolean} isShown
+ *     Shows all the grid area highlights for the current grid if isShown is true.
  * - showGridArea(areaName)
  *     @param  {String} areaName
  *     Shows the grid area highlight for the given area name.
- * - showAllGridAreas
- *     Shows all the grid area highlights for the current grid.
+ * - showGridCell({ gridFragmentIndex: Number, rowNumber: Number, columnNumber: Number })
+ *     @param  {Object} { gridFragmentIndex: Number, rowNumber: Number,
+ *                        columnNumber: Number }
+ *     An object containing the grid fragment index, row and column numbers to the
+ *     corresponding grid cell to highlight for the current grid.
  * - showGridLineNumbers(isShown)
- *     @param  {Boolean}
+ *     @param  {Boolean} isShown
  *     Displays the grid line numbers on the grid lines if isShown is true.
  * - showInfiniteLines(isShown)
  *     @param  {Boolean} isShown
  *     Displays an infinite line to represent the grid lines if isShown is true.
  *
  * Structure:
  * <div class="highlighter-container">
  *   <canvas id="css-grid-canvas" class="css-grid-canvas">
  *   <svg class="css-grid-elements" hidden="true">
  *     <g class="css-grid-regions">
  *       <path class="css-grid-areas" points="..." />
+ *       <path class="css-grid-cells" points="..." />
  *     </g>
  *   </svg>
- *   <div class="css-grid-infobar-container">
+ *   <div class="css-grid-area-infobar-container">
  *     <div class="css-grid-infobar">
  *       <div class="css-grid-infobar-text">
- *         <span class="css-grid-infobar-areaname">Grid Area Name</span>
- *         <span class="css-grid-infobar-dimensions"Grid Area Dimensions></span>
+ *         <span class="css-grid-area-infobar-name">Grid Area Name</span>
+ *         <span class="css-grid-area-infobar-dimensions"Grid Area Dimensions></span>
+ *       </div>
+ *     </div>
+ *   </div>
+ *   <div class="css-grid-cell-infobar-container">
+ *     <div class="css-grid-infobar">
+ *       <div class="css-grid-infobar-text">
+ *         <span class="css-grid-cell-infobar-position">Grid Cell Position</span>
+ *         <span class="css-grid-cell-infobar-dimensions"Grid Cell Dimensions></span>
  *       </div>
  *     </div>
  *   </div>
  * </div>
  */
 function CssGridHighlighter(highlighterEnv) {
   AutoRefreshHighlighter.call(this, highlighterEnv);
 
@@ -178,58 +195,114 @@ CssGridHighlighter.prototype = extend(Au
       parent: regions,
       attributes: {
         "class": "areas",
         "id": "areas"
       },
       prefix: this.ID_CLASS_PREFIX
     });
 
-    // Building the grid infobar markup
-    let infobarContainer = createNode(this.win, {
+    createSVGNode(this.win, {
+      nodeType: "path",
+      parent: regions,
+      attributes: {
+        "class": "cells",
+        "id": "cells"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+
+    // Building the grid area infobar markup
+    let areaInfobarContainer = createNode(this.win, {
       parent: container,
       attributes: {
-        "class": "infobar-container",
-        "id": "infobar-container",
+        "class": "area-infobar-container",
+        "id": "area-infobar-container",
         "position": "top",
         "hidden": "true"
       },
       prefix: this.ID_CLASS_PREFIX
     });
 
-    let infobar = createNode(this.win, {
-      parent: infobarContainer,
+    let areaInfobar = createNode(this.win, {
+      parent: areaInfobarContainer,
       attributes: {
         "class": "infobar"
       },
       prefix: this.ID_CLASS_PREFIX
     });
 
-    let textbox = createNode(this.win, {
-      parent: infobar,
+    let areaTextbox = createNode(this.win, {
+      parent: areaInfobar,
       attributes: {
         "class": "infobar-text"
       },
       prefix: this.ID_CLASS_PREFIX
     });
     createNode(this.win, {
       nodeType: "span",
-      parent: textbox,
+      parent: areaTextbox,
       attributes: {
-        "class": "infobar-areaname",
-        "id": "infobar-areaname"
+        "class": "area-infobar-name",
+        "id": "area-infobar-name"
       },
       prefix: this.ID_CLASS_PREFIX
     });
     createNode(this.win, {
       nodeType: "span",
-      parent: textbox,
+      parent: areaTextbox,
+      attributes: {
+        "class": "area-infobar-dimensions",
+        "id": "area-infobar-dimensions"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+
+    // Building the grid cell infobar markup
+    let cellInfobarContainer = createNode(this.win, {
+      parent: container,
+      attributes: {
+        "class": "cell-infobar-container",
+        "id": "cell-infobar-container",
+        "position": "top",
+        "hidden": "true"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+
+    let cellInfobar = createNode(this.win, {
+      parent: cellInfobarContainer,
       attributes: {
-        "class": "infobar-dimensions",
-        "id": "infobar-dimensions"
+        "class": "infobar"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+
+    let cellTextbox = createNode(this.win, {
+      parent: cellInfobar,
+      attributes: {
+        "class": "infobar-text"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+    createNode(this.win, {
+      nodeType: "span",
+      parent: cellTextbox,
+      attributes: {
+        "class": "cell-infobar-position",
+        "id": "cell-infobar-position"
+      },
+      prefix: this.ID_CLASS_PREFIX
+    });
+    createNode(this.win, {
+      nodeType: "span",
+      parent: cellTextbox,
+      attributes: {
+        "class": "cell-infobar-dimensions",
+        "id": "cell-infobar-dimensions"
       },
       prefix: this.ID_CLASS_PREFIX
     });
 
     return container;
   },
 
   destroy() {
@@ -323,49 +396,72 @@ CssGridHighlighter.prototype = extend(Au
     if (Services.prefs.getBoolPref(CSS_GRID_ENABLED_PREF) && !this.isGrid()) {
       this.hide();
       return false;
     }
 
     // The grid pattern cache should be cleared in case the color changed.
     this._clearCache();
 
+    // Hide the canvas, grid element highlights and infobar.
+    this._hide();
+
     return this._update();
   },
 
   _clearCache() {
     gCachedGridPattern.delete(ROW_KEY);
     gCachedGridPattern.delete(COLUMN_KEY);
   },
 
   /**
    * Shows the grid area highlight for the given area name.
    *
    * @param  {String} areaName
    *         Grid area name.
    */
   showGridArea(areaName) {
     this.renderGridArea(areaName);
-    this._showGridArea();
   },
 
   /**
    * Shows all the grid area highlights for the current grid.
    */
   showAllGridAreas() {
     this.renderGridArea();
-    this._showGridArea();
   },
 
   /**
    * Clear the grid area highlights.
    */
   clearGridAreas() {
-    let box = this.getElement("areas");
-    box.setAttribute("d", "");
+    let areas = this.getElement("areas");
+    areas.setAttribute("d", "");
+  },
+
+  /**
+   * Shows the grid cell highlight for the given grid cell options.
+   *
+   * @param  {Number} options.gridFragmentIndex
+   *         Index of the grid fragment to render the grid cell highlight.
+   * @param  {Number} options.rowNumber
+   *         Row number of the grid cell to highlight.
+   * @param  {Number} options.columnNumber
+   *         Column number of the grid cell to highlight.
+   */
+  showGridCell({ gridFragmentIndex, rowNumber, columnNumber }) {
+    this.renderGridCell(gridFragmentIndex, rowNumber, columnNumber);
+  },
+
+  /**
+   * Clear the grid cell highlights.
+   */
+  clearGridCell() {
+    let cells = this.getElement("cells");
+    cells.setAttribute("d", "");
   },
 
   /**
    * Checks if the current node has a CSS Grid layout.
    *
    * @return  {Boolean} true if the current node has a CSS grid layout, false otherwise.
    */
   isGrid() {
@@ -417,76 +513,97 @@ CssGridHighlighter.prototype = extend(Au
 
     // Display the grid area highlights if needed.
     if (this.options.showAllGridAreas) {
       this.showAllGridAreas();
     } else if (this.options.showGridArea) {
       this.showGridArea(this.options.showGridArea);
     }
 
+    // Display the grid cell highlights if needed.
+    if (this.options.showGridCell) {
+      this.showGridCell(this.options.showGridCell);
+    }
+
     this._showGrid();
+    this._showGridElements();
 
     root.setAttribute("style",
       `position:absolute; width:${width}px;height:${height}px; overflow:hidden`);
 
     setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement);
     return true;
   },
 
   /**
-   * Update the grid information displayed in the grid info bar.
+   * Update the grid information displayed in the grid area info bar.
    *
    * @param  {GridArea} area
    *         The grid area object.
    * @param  {Number} x1
    *         The first x-coordinate of the grid area rectangle.
    * @param  {Number} x2
    *         The second x-coordinate of the grid area rectangle.
    * @param  {Number} y1
    *         The first y-coordinate of the grid area rectangle.
    * @param  {Number} y2
    *         The second y-coordinate of the grid area rectangle.
    */
-  _updateInfobar(area, x1, x2, y1, y2) {
+  _updateGridAreaInfobar(area, x1, x2, y1, y2) {
     let width = x2 - x1;
     let height = y2 - y1;
     let dim = parseFloat(width.toPrecision(6)) +
               " \u00D7 " +
               parseFloat(height.toPrecision(6));
 
-    this.getElement("infobar-areaname").setTextContent(area.name);
-    this.getElement("infobar-dimensions").setTextContent(dim);
+    this.getElement("area-infobar-name").setTextContent(area.name);
+    this.getElement("area-infobar-dimensions").setTextContent(dim);
+
+    let container = this.getElement("area-infobar-container");
+    this._moveInfobar(container, x1, x2, y1, y2);
+  },
 
-    this._moveInfobar(x1, x2, y1, y2);
+  _updateGridCellInfobar(rowNumber, columnNumber, x1, x2, y1, y2) {
+    let width = x2 - x1;
+    let height = y2 - y1;
+    let dim = parseFloat(width.toPrecision(6)) +
+              " \u00D7 " +
+              parseFloat(height.toPrecision(6));
+    let position = `${rowNumber}\/${columnNumber}`;
+
+    this.getElement("cell-infobar-position").setTextContent(position);
+    this.getElement("cell-infobar-dimensions").setTextContent(dim);
+
+    let container = this.getElement("cell-infobar-container");
+    this._moveInfobar(container, x1, x2, y1, y2);
   },
 
   /**
-   * Move the grid infobar to the right place in the highlighter.
+   * Move the given grid infobar to the right place in the highlighter.
    *
    * @param  {Number} x1
-   *         The first x-coordinate of the grid area rectangle.
+   *         The first x-coordinate of the grid rectangle.
    * @param  {Number} x2
-   *         The second x-coordinate of the grid area rectangle.
+   *         The second x-coordinate of the grid rectangle.
    * @param  {Number} y1
-   *         The first y-coordinate of the grid area rectangle.
+   *         The first y-coordinate of the grid rectangle.
    * @param  {Number} y2
-   *         The second y-coordinate of the grid area rectangle.
+   *         The second y-coordinate of the grid rectangle.
    */
-  _moveInfobar(x1, x2, y1, y2) {
+  _moveInfobar(container, x1, x2, y1, y2) {
     let bounds = {
       bottom: y2,
       height: y2 - y1,
       left: x1,
       right: x2,
       top: y1,
       width: x2 - x1,
       x: x1,
       y: y1,
     };
-    let container = this.getElement("infobar-container");
 
     moveInfobar(container, bounds, this.win);
   },
 
   clearCanvas(width, height) {
     let ratio = parseFloat((this.win.devicePixelRatio || 1).toFixed(2));
 
     // Resize the canvas taking the dpr into account so as to have crisp lines.
@@ -610,17 +727,17 @@ CssGridHighlighter.prototype = extend(Au
    *         The line position along the x-axis for a column grid line and
    *         y-axis for a row grid line.
    * @param  {Number} startPos
    *         The start position of the cross side of the grid line.
    * @param  {Number} endPos
    *         The end position of the cross side of the grid line.
    * @param  {String} dimensionType
    *         The grid dimension type which is either the constant COLUMNS or ROWS.
-   * @param  {[type]} lineType
+   * @param  {String} lineType
    *         The grid line type - "edge", "explicit", or "implicit".
    */
   renderLine(linePos, startPos, endPos, dimensionType, lineType) {
     this.ctx.save();
     this.ctx.setLineDash(GRID_LINES_PROPERTIES[lineType].lineDash);
     this.ctx.beginPath();
     this.ctx.translate(.5, .5);
 
@@ -734,56 +851,108 @@ CssGridHighlighter.prototype = extend(Au
         let path = "M" + x1 + "," + y1 + " " +
                    "L" + x2 + "," + y1 + " " +
                    "L" + x2 + "," + y2 + " " +
                    "L" + x1 + "," + y2;
         paths.push(path);
 
         // Update and show the info bar when only displaying a single grid area.
         if (areaName) {
-          this._updateInfobar(area, x1, x2, y1, y2);
-          this._showInfoBar();
+          this._updateGridAreaInfobar(area, x1, x2, y1, y2);
+          this._showGridAreaInfoBar();
         }
       }
     }
 
-    let box = this.getElement("areas");
-    box.setAttribute("d", paths.join(" "));
+    let areas = this.getElement("areas");
+    areas.setAttribute("d", paths.join(" "));
   },
 
   /**
-   * Hide the highlighter, the canvas and the infobar.
+   * Render the grid cell highlight for the given grid fragment index, row and column
+   * number.
+   *
+   * @param  {Number} gridFragmentIndex
+   *         Index of the grid fragment to render the grid cell highlight.
+   * @param  {Number} rowNumber
+   *         Row number of the grid cell to highlight.
+   * @param  {Number} columnNumber
+   *         Column number of the grid cell to highlight.
+   */
+  renderGridCell(gridFragmentIndex, rowNumber, columnNumber) {
+    let fragment = this.gridData[gridFragmentIndex];
+    if (!fragment) {
+      return;
+    }
+
+    let row = fragment.rows.tracks[rowNumber - 1];
+    let column = fragment.cols.tracks[columnNumber - 1];
+
+    if (!row || !column) {
+      return;
+    }
+
+    let currentZoom = getCurrentZoom(this.win);
+    let {bounds} = this.currentQuads.content[gridFragmentIndex];
+
+    let x1 = column.start + (bounds.left / currentZoom);
+    let x2 = column.start + column.breadth + (bounds.left / currentZoom);
+    let y1 = row.start + (bounds.top / currentZoom);
+    let y2 = row.start + row.breadth + (bounds.top / currentZoom);
+
+    let path = "M" + x1 + "," + y1 + " " +
+               "L" + x2 + "," + y1 + " " +
+               "L" + x2 + "," + y2 + " " +
+               "L" + x1 + "," + y2;
+    let cells = this.getElement("cells");
+    cells.setAttribute("d", path);
+
+    this._updateGridCellInfobar(rowNumber, columnNumber, x1, x2, y1, y2);
+    this._showGridCellInfoBar();
+  },
+
+  /**
+   * Hide the highlighter, the canvas and the infobars.
    */
   _hide() {
     setIgnoreLayoutChanges(true);
     this._hideGrid();
-    this._hideGridArea();
-    this._hideInfoBar();
+    this._hideGridElements();
+    this._hideGridAreaInfoBar();
+    this._hideGridCellInfoBar();
     setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement);
   },
 
   _hideGrid() {
     this.getElement("canvas").setAttribute("hidden", "true");
   },
 
   _showGrid() {
     this.getElement("canvas").removeAttribute("hidden");
   },
 
-  _hideGridArea() {
+  _hideGridElements() {
     this.getElement("elements").setAttribute("hidden", "true");
   },
 
-  _showGridArea() {
+  _showGridElements() {
     this.getElement("elements").removeAttribute("hidden");
   },
 
-  _hideInfoBar() {
-    this.getElement("infobar-container").setAttribute("hidden", "true");
+  _hideGridAreaInfoBar() {
+    this.getElement("area-infobar-container").setAttribute("hidden", "true");
   },
 
-  _showInfoBar() {
-    this.getElement("infobar-container").removeAttribute("hidden");
+  _showGridAreaInfoBar() {
+    this.getElement("area-infobar-container").removeAttribute("hidden");
+  },
+
+  _hideGridCellInfoBar() {
+    this.getElement("cell-infobar-container").setAttribute("hidden", "true");
+  },
+
+  _showGridCellInfoBar() {
+    this.getElement("cell-infobar-container").removeAttribute("hidden");
   },
 
 });
 
 exports.CssGridHighlighter = CssGridHighlighter;
--- a/dom/audiochannel/moz.build
+++ b/dom/audiochannel/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIAudioChannelAgent.idl',
     'nsIAudioChannelService.idl',
 ]
 
 XPIDL_MODULE = 'dom_audiochannel'
 
 EXPORTS += [
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'mozIDOMWindow.idl',
     'nsIContentPolicy.idl',
     'nsIContentPolicyBase.idl',
     'nsIDocumentEncoder.idl',
     'nsIDOMDataChannel.idl',
--- a/dom/encoding/moz.build
+++ b/dom/encoding/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Internationalization")
+
 EXPORTS.mozilla.dom += [
     'EncodingUtils.h',
     'FallbackEncoding.h',
     'TextDecoder.h',
     'TextEncoder.h',
 ]
 
 UNIFIED_SOURCES += [
--- a/dom/events/DeviceMotionEvent.cpp
+++ b/dom/events/DeviceMotionEvent.cpp
@@ -65,16 +65,21 @@ DeviceMotionEvent::InitDeviceMotionEvent
                            aAccelIncludingGravity.mZ);
 
   mRotationRate = new DeviceRotationRate(this, aRotationRate.mAlpha,
                                          aRotationRate.mBeta,
                                          aRotationRate.mGamma);
   mInterval = aInterval;
   if (!aTimeStamp.IsNull()) {
     mEvent->mTime = aTimeStamp.Value();
+
+    static mozilla::TimeStamp sInitialNow = mozilla::TimeStamp::Now();
+    static uint64_t sInitialEventTime = aTimeStamp.Value();
+    mEvent->mTimeStamp = sInitialNow + mozilla::TimeDuration::FromMicroseconds(
+      aTimeStamp.Value() - sInitialEventTime);
   }
 }
 
 already_AddRefed<DeviceMotionEvent>
 DeviceMotionEvent::Constructor(const GlobalObject& aGlobal,
                                const nsAString& aType,
                                const DeviceMotionEventInit& aEventInitDict,
                                ErrorResult& aRv)
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Events")
+
 MOCHITEST_MANIFESTS += [
     'test/mochitest.ini',
     'test/pointerevents/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 XPIDL_SOURCES += [
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -272,31 +272,33 @@ private:
 
 } // namespace
 
 /*static*/ already_AddRefed<Request>
 Request::Constructor(const GlobalObject& aGlobal,
                      const RequestOrUSVString& aInput,
                      const RequestInit& aInit, ErrorResult& aRv)
 {
-  nsCOMPtr<nsIInputStream> temporaryBody;
+  bool hasCopiedBody = false;
   RefPtr<InternalRequest> request;
 
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
 
   if (aInput.IsRequest()) {
     RefPtr<Request> inputReq = &aInput.GetAsRequest();
     nsCOMPtr<nsIInputStream> body;
     inputReq->GetBody(getter_AddRefs(body));
     if (inputReq->BodyUsed()) {
       aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
       return nullptr;
     }
+
+    // The body will be copied when GetRequestConstructorCopy() is executed.
     if (body) {
-      temporaryBody = body;
+      hasCopiedBody = true;
     }
 
     request = inputReq->GetInternalRequest();
   } else {
     // aInput is USVString.
     // We need to get url before we create a InternalRequest.
     nsAutoString input;
     input.Assign(aInput.GetAsUSVString());
@@ -333,18 +335,17 @@ Request::Constructor(const GlobalObject&
 
   RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
   RequestCredentials credentials =
     aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
                                    : fallbackCredentials;
 
   if (mode == RequestMode::Navigate ||
       (aInit.IsAnyMemberPresent() && request->Mode() == RequestMode::Navigate)) {
-    aRv.ThrowTypeError<MSG_INVALID_REQUEST_MODE>(NS_LITERAL_STRING("navigate"));
-    return nullptr;
+    mode = RequestMode::Same_origin;
   }
 
   if (aInit.IsAnyMemberPresent()) {
     request->SetReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR));
     request->SetReferrerPolicy(ReferrerPolicy::_empty);
   }
   if (aInit.mReferrer.WasPassed()) {
     const nsString& referrer = aInit.mReferrer.Value();
@@ -369,21 +370,17 @@ Request::Constructor(const GlobalObject&
         uri->GetSpec(spec);
         CopyUTF8toUTF16(spec, referrerURL);
         if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
           nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
           if (principal) {
             nsresult rv = principal->CheckMayLoad(uri, /* report */ false,
                                                   /* allowIfInheritsPrincipal */ false);
             if (NS_FAILED(rv)) {
-              nsAutoCString globalOrigin;
-              principal->GetOrigin(globalOrigin);
-              aRv.ThrowTypeError<MSG_CROSS_ORIGIN_REFERRER_URL>(referrer,
-                                                                NS_ConvertUTF8toUTF16(globalOrigin));
-              return nullptr;
+              referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
             }
           }
         }
       } else {
         RefPtr<URL> url = ParseURLFromWorker(aGlobal, referrer, aRv);
         if (NS_WARN_IF(aRv.Failed())) {
           aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
           return nullptr;
@@ -398,21 +395,20 @@ Request::Constructor(const GlobalObject&
           nsresult rv = NS_OK;
           // ReferrerSameOriginChecker uses a sync loop to get the main thread
           // to perform the same-origin check.  Overall, on Workers this method
           // can create 3 sync loops (two for constructing URLs and one here) so
           // in the future we may want to optimize it all by off-loading all of
           // this work in a single sync loop.
           RefPtr<ReferrerSameOriginChecker> checker =
             new ReferrerSameOriginChecker(worker, referrerURL, rv);
-          checker->Dispatch(Terminating, aRv);
-          if (aRv.Failed() || NS_FAILED(rv)) {
-            aRv.ThrowTypeError<MSG_CROSS_ORIGIN_REFERRER_URL>(referrer,
-                                                              worker->GetLocationInfo().mOrigin);
-            return nullptr;
+          IgnoredErrorResult error;
+          checker->Dispatch(Terminating, error);
+          if (error.Failed() || NS_FAILED(rv)) {
+            referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
           }
         }
       }
       request->SetReferrer(referrerURL);
     }
   }
 
   if (aInit.mReferrerPolicy.WasPassed()) {
@@ -530,17 +526,17 @@ Request::Constructor(const GlobalObject&
   }
 
   requestHeaders->Fill(*headers, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   if ((aInit.mBody.WasPassed() && !aInit.mBody.Value().IsNull()) ||
-      temporaryBody) {
+      hasCopiedBody) {
     // HEAD and GET are not allowed to have a body.
     nsAutoCString method;
     request->GetMethod(method);
     // method is guaranteed to be uppercase due to step 14.2 above.
     if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
       aRv.ThrowTypeError<MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD>();
       return nullptr;
     }
@@ -556,29 +552,34 @@ Request::Constructor(const GlobalObject&
       aRv = ExtractByteStreamFromBody(bodyInit,
                                       getter_AddRefs(stream),
                                       contentTypeWithCharset,
                                       contentLengthUnused);
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
 
-      temporaryBody = stream;
+      nsCOMPtr<nsIInputStream> temporaryBody = stream;
 
       if (!contentTypeWithCharset.IsVoid() &&
           !requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
         requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
                                contentTypeWithCharset, aRv);
       }
 
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
 
       request->ClearCreatedByFetchEvent();
+
+      if (hasCopiedBody) {
+        request->SetBody(nullptr);
+      }
+
       request->SetBody(temporaryBody);
     }
   }
 
   RefPtr<Request> domRequest = new Request(global, request);
   domRequest->SetMimeType();
 
   if (aInput.IsRequest()) {
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'BodyExtractor.h',
     'ChannelInfo.h',
     'Fetch.h',
     'FetchDriver.h',
     'FetchIPCTypes.h',
     'FetchUtil.h',
     'Headers.h',
--- a/dom/file/moz.build
+++ b/dom/file/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 DIRS += ['ipc']
 
 XPIDL_SOURCES += [
     'nsIDOMBlob.idl',
     'nsIDOMFileList.idl',
 ]
 
 XPIDL_MODULE = 'dom_file'
--- a/dom/filehandle/moz.build
+++ b/dom/filehandle/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom.filehandle += [
     'ActorsChild.h',
     'ActorsParent.h',
     'SerializationHelpers.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'FileHandleBase.h',
--- a/dom/filesystem/moz.build
+++ b/dom/filesystem/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 DIRS += ['compat']
 
 TEST_DIRS += ['tests']
 
 EXPORTS.mozilla.dom += [
     'DeviceStorageFileSystem.h',
     'Directory.h',
     'FileSystemBase.h',
--- a/dom/grid/moz.build
+++ b/dom/grid/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
+
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 EXPORTS.mozilla.dom += [
     'Grid.h',
     'GridArea.h',
     'GridDimension.h',
     'GridLine.h',
     'GridLines.h',
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 MOCHITEST_MANIFESTS += [
     'test/forms/mochitest.ini',
     'test/imports/mochitest.ini',
     'test/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += [
     'test/chrome.ini',
--- a/dom/imptests/moz.build
+++ b/dom/imptests/moz.build
@@ -1,14 +1,29 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("html/webgl/**"):
+    BUG_COMPONENT = ("Core", "Canvas 2D")
+
+with Files("html/typedarrays/**"):
+    BUG_COMPONENT = ("Core", "Javascript: Standard Library")
+
+with Files("html/js/**"):
+    BUG_COMPONENT = ("Core", "Javascript: Standard Library")
+
+with Files("html/html/**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
 MOCHITEST_MANIFESTS += [
     'html/mochitest.ini',
     'webapps/mochitest.ini',
 ]
 
 MOCHITEST_MANIFESTS += [
     'failures/html/typedarrays/mochitest.ini',
 ]
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -985,17 +985,18 @@ protected:
 
 class WorkerPermissionChallenge final : public Runnable
 {
 public:
   WorkerPermissionChallenge(WorkerPrivate* aWorkerPrivate,
                             BackgroundFactoryRequestChild* aActor,
                             IDBFactory* aFactory,
                             const PrincipalInfo& aPrincipalInfo)
-    : mWorkerPrivate(aWorkerPrivate)
+    : Runnable("indexedDB::WorkerPermissionChallenge")
+    , mWorkerPrivate(aWorkerPrivate)
     , mActor(aActor)
     , mFactory(aFactory)
     , mPrincipalInfo(aPrincipalInfo)
   {
     MOZ_ASSERT(mWorkerPrivate);
     MOZ_ASSERT(aActor);
     MOZ_ASSERT(aFactory);
     mWorkerPrivate->AssertIsOnWorkerThread();
@@ -1004,17 +1005,17 @@ public:
   bool
   Dispatch()
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
     if (NS_WARN_IF(!mWorkerPrivate->ModifyBusyCountFromWorker(true))) {
       return false;
     }
 
-    if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
+    if (NS_WARN_IF(NS_FAILED(mWorkerPrivate->DispatchToMainThread(this)))) {
       mWorkerPrivate->ModifyBusyCountFromWorker(false);
       return false;
     }
 
     return true;
   }
 
   NS_IMETHOD
@@ -1101,16 +1102,18 @@ private:
     }
 
     TabChild* tabChild = TabChild::GetFrom(window);
     MOZ_ASSERT(tabChild);
 
     IPC::Principal ipcPrincipal(principal);
 
     auto* actor = new WorkerPermissionRequestChildProcessActor(this);
+    tabChild->SetEventTargetForActor(actor, wp->MainThreadEventTarget());
+    MOZ_ASSERT(actor->GetActorEventTarget());
     tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
     return false;
   }
 
 private:
   WorkerPrivate* mWorkerPrivate;
   BackgroundFactoryRequestChild* mActor;
   RefPtr<IDBFactory> mFactory;
@@ -1159,17 +1162,18 @@ class BackgroundRequestChild::Preprocess
   nsTArray<StreamPair> mStreamPairs;
   nsTArray<RefPtr<JS::WasmModule>> mModuleSet;
   BackgroundRequestChild* mActor;
   uint32_t mModuleSetIndex;
   nsresult mResultCode;
 
 public:
   PreprocessHelper(uint32_t aModuleSetIndex, BackgroundRequestChild* aActor)
-    : mOwningThread(NS_GetCurrentThread())
+    : CancelableRunnable("indexedDB::BackgroundRequestChild::PreprocessHelper")
+    , mOwningThread(aActor->GetActorEventTarget())
     , mActor(aActor)
     , mModuleSetIndex(aModuleSetIndex)
     , mResultCode(NS_OK)
   {
     AssertIsOnOwningThread();
     MOZ_ASSERT(aActor);
     aActor->AssertIsOnOwningThread();
   }
@@ -1395,16 +1399,30 @@ BackgroundFactoryChild::DeallocPBackgrou
                                             PBackgroundIDBDatabaseChild* aActor)
 {
   MOZ_ASSERT(aActor);
 
   delete static_cast<BackgroundDatabaseChild*>(aActor);
   return true;
 }
 
+mozilla::ipc::IPCResult
+BackgroundFactoryChild::RecvPBackgroundIDBDatabaseConstructor(
+                                    PBackgroundIDBDatabaseChild* aActor,
+                                    const DatabaseSpec& aSpec,
+                                    PBackgroundIDBFactoryRequestChild* aRequest)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aActor);
+  MOZ_ASSERT(aActor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
+
+  return IPC_OK();
+}
+
 /*******************************************************************************
  * BackgroundFactoryRequestChild
  ******************************************************************************/
 
 BackgroundFactoryRequestChild::BackgroundFactoryRequestChild(
                                                IDBFactory* aFactory,
                                                IDBOpenDBRequest* aOpenRequest,
                                                bool aIsDeleteOp,
@@ -1625,16 +1643,18 @@ BackgroundFactoryRequestChild::RecvPermi
 
   RefPtr<TabChild> tabChild = mFactory->GetTabChild();
   MOZ_ASSERT(tabChild);
 
   IPC::Principal ipcPrincipal(principal);
 
   auto* actor = new PermissionRequestChildProcessActor(this, mFactory);
 
+  tabChild->SetEventTargetForActor(actor, this->GetActorEventTarget());
+  MOZ_ASSERT(actor->GetActorEventTarget());
   tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 BackgroundFactoryRequestChild::RecvBlocked(const uint64_t& aCurrentVersion)
 {
@@ -1848,16 +1868,18 @@ BackgroundDatabaseChild::RecvPBackground
                             PBackgroundIDBVersionChangeTransactionChild* aActor,
                             const uint64_t& aCurrentVersion,
                             const uint64_t& aRequestedVersion,
                             const int64_t& aNextObjectStoreId,
                             const int64_t& aNextIndexId)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aActor);
+  MOZ_ASSERT(aActor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
   MOZ_ASSERT(mOpenRequestActor);
 
   MaybeCollectGarbageOnIPCMessage();
 
   EnsureDOMObject();
 
   auto* actor = static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
 
@@ -3122,17 +3144,18 @@ class BackgroundCursorChild::DelayedActi
 
   BackgroundCursorChild* mActor;
   RefPtr<IDBRequest> mRequest;
   ActionFunc mActionFunc;
 
 public:
   explicit
   DelayedActionRunnable(BackgroundCursorChild* aActor, ActionFunc aActionFunc)
-    : mActor(aActor)
+    : CancelableRunnable("indexedDB::BackgroundCursorChild::DelayedActionRunnable")
+    , mActor(aActor)
     , mRequest(aActor->mRequest)
     , mActionFunc(aActionFunc)
   {
     MOZ_ASSERT(aActor);
     aActor->AssertIsOnOwningThread();
     MOZ_ASSERT(mRequest);
     MOZ_ASSERT(mActionFunc);
   }
@@ -3275,17 +3298,18 @@ BackgroundCursorChild::HandleResponse(co
   }
 
   ResultHelper helper(mRequest, mTransaction, &JS::NullHandleValue);
   DispatchSuccessEvent(&helper);
 
   if (!mCursor) {
     nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedActionRunnable(
       this, &BackgroundCursorChild::SendDeleteMeInternal);
-    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable));
+      MOZ_ALWAYS_SUCCEEDS(this->GetActorEventTarget()->
+        Dispatch(deleteRunnable.forget(), NS_DISPATCH_NORMAL));
   }
 }
 
 void
 BackgroundCursorChild::HandleResponse(
     const nsTArray<ObjectStoreCursorResponse>& aResponses)
 {
   AssertIsOnOwningThread();
--- a/dom/indexedDB/ActorsChild.h
+++ b/dom/indexedDB/ActorsChild.h
@@ -210,16 +210,23 @@ private:
   AllocPBackgroundIDBDatabaseChild(const DatabaseSpec& aSpec,
                                    PBackgroundIDBFactoryRequestChild* aRequest)
                                    override;
 
   virtual bool
   DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild* aActor)
                                      override;
 
+  mozilla::ipc::IPCResult
+  RecvPBackgroundIDBDatabaseConstructor(
+                                    PBackgroundIDBDatabaseChild* aActor,
+                                    const DatabaseSpec& aSpec,
+                                    PBackgroundIDBFactoryRequestChild* aRequest)
+                                    override;
+
   bool
   SendDeleteMe() = delete;
 };
 
 class BackgroundDatabaseChild;
 
 class BackgroundRequestChildBase
 {
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -27,17 +27,17 @@ class StreamWrapper final
   nsCOMPtr<nsIEventTarget> mOwningThread;
   nsCOMPtr<nsIInputStream> mInputStream;
   RefPtr<IDBFileHandle> mFileHandle;
   bool mFinished;
 
 public:
   StreamWrapper(nsIInputStream* aInputStream,
                 IDBFileHandle* aFileHandle)
-    : mOwningThread(NS_GetCurrentThread())
+    : mOwningThread(aFileHandle->GetMutableFile()->Database()->EventTarget())
     , mInputStream(aInputStream)
     , mFileHandle(aFileHandle)
     , mFinished(false)
   {
     AssertIsOnOwningThread();
     MOZ_ASSERT(aInputStream);
     MOZ_ASSERT(aFileHandle);
     aFileHandle->AssertIsOnOwningThread();
@@ -81,18 +81,20 @@ private:
   void
   Destroy()
   {
     if (IsOnOwningThread()) {
       delete this;
       return;
     }
 
-    nsCOMPtr<nsIRunnable> destroyRunnable =
-      NewNonOwningRunnableMethod(this, &StreamWrapper::Destroy);
+    RefPtr<Runnable> destroyRunnable =
+      NewNonOwningRunnableMethod("StreamWrapper::Destroy",
+                                 this,
+                                 &StreamWrapper::Destroy);
 
     MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(destroyRunnable,
                                                 NS_DISPATCH_NORMAL));
   }
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
@@ -106,17 +108,18 @@ class StreamWrapper::CloseRunnable final
   RefPtr<StreamWrapper> mStreamWrapper;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
 private:
   explicit
   CloseRunnable(StreamWrapper* aStreamWrapper)
-    : mStreamWrapper(aStreamWrapper)
+    : Runnable("StreamWrapper::CloseRunnable")
+    , mStreamWrapper(aStreamWrapper)
   { }
 
   ~CloseRunnable()
   { }
 
   NS_IMETHOD
   Run() override;
 };
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -255,16 +255,23 @@ PRThread*
 IDBDatabase::OwningThread() const
 {
   MOZ_ASSERT(mFactory);
   return mFactory->OwningThread();
 }
 
 #endif // DEBUG
 
+nsIEventTarget*
+IDBDatabase::EventTarget() const
+{
+  AssertIsOnOwningThread();
+  return Factory()->EventTarget();
+}
+
 void
 IDBDatabase::CloseInternal()
 {
   AssertIsOnOwningThread();
 
   if (!mClosed) {
     mClosed = true;
 
@@ -705,16 +712,18 @@ IDBDatabase::Transaction(JSContext* aCx,
                transaction->LoggingSerialNumber(),
                IDB_LOG_STRINGIFY(this),
                IDB_LOG_STRINGIFY(transaction));
 
   MOZ_ALWAYS_TRUE(
     mBackgroundActor->SendPBackgroundIDBTransactionConstructor(actor,
                                                                sortedStoreNames,
                                                                mode));
+  MOZ_ASSERT(actor->GetActorEventTarget(),
+    "The event target shall be inherited from it manager actor.");
 
   transaction->SetBackgroundActor(actor);
 
   if (mode == IDBTransaction::CLEANUP) {
     ExpireFileActors(/* aExpireAll */ true);
   }
 
   transaction.forget(aTransaction);
@@ -767,16 +776,19 @@ IDBDatabase::CreateMutableFile(JSContext
                "IndexedDB %s: C R[%llu]: IDBDatabase.createMutableFile()",
                IDB_LOG_ID_STRING(),
                request->LoggingSerialNumber(),
                IDB_LOG_STRINGIFY(this),
                NS_ConvertUTF16toUTF8(aName).get());
 
   mBackgroundActor->SendPBackgroundIDBDatabaseRequestConstructor(actor, params);
 
+  MOZ_ASSERT(actor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
+
   return request.forget();
 }
 
 void
 IDBDatabase::RegisterTransaction(IDBTransaction* aTransaction)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aTransaction);
@@ -937,16 +949,19 @@ IDBDatabase::GetOrCreateFileActorForBlob
       auto* dbFile = new DatabaseFile(this);
 
       actor =
         mBackgroundActor->SendPBackgroundIDBDatabaseFileConstructor(dbFile,
                                                                     blobChild);
       if (NS_WARN_IF(!actor)) {
         return nullptr;
       }
+
+      MOZ_ASSERT(actor->GetActorEventTarget(),
+        "The event target shall be inherited from its manager actor.");
     } else {
       // Make sure that the input stream we get here is one that can actually be
       // serialized to PBackground.
       PBackgroundChild* backgroundManager =
         mBackgroundActor->Manager()->Manager();
       MOZ_ASSERT(backgroundManager);
 
       auto* blobChild =
@@ -957,16 +972,19 @@ IDBDatabase::GetOrCreateFileActorForBlob
       auto* dbFile = new DatabaseFile(this);
 
       actor =
         mBackgroundActor->SendPBackgroundIDBDatabaseFileConstructor(dbFile,
                                                                     blobChild);
       if (NS_WARN_IF(!actor)) {
         return nullptr;
       }
+
+      MOZ_ASSERT(actor->GetActorEventTarget(),
+        "The event target shall be inherited from its manager actor.");
     }
 
     MOZ_ASSERT(actor);
 
     mFileActors.Put(weakRef, actor);
   }
 
   MOZ_ASSERT(actor);
@@ -1031,29 +1049,31 @@ void
 IDBDatabase::DelayedMaybeExpireFileActors()
 {
   AssertIsOnOwningThread();
 
   if (!mBackgroundActor || !mFileActors.Count()) {
     return;
   }
 
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod<bool>(this,
+  RefPtr<Runnable> runnable =
+    NewRunnableMethod<bool>("IDBDatabase::ExpireFileActors",
+                            this,
                             &IDBDatabase::ExpireFileActors,
                             /* aExpireAll */ false);
   MOZ_ASSERT(runnable);
 
   if (!NS_IsMainThread()) {
     // Wrap as a nsICancelableRunnable to make workers happy.
-    nsCOMPtr<nsIRunnable> cancelable = new CancelableRunnableWrapper(runnable);
+    RefPtr<Runnable> cancelable = new CancelableRunnableWrapper(runnable);
     cancelable.swap(runnable);
   }
 
-  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(runnable));
+  MOZ_ALWAYS_SUCCEEDS(
+    EventTarget()->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
 }
 
 nsresult
 IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
                           PersistenceType* aPersistenceType)
 {
   using mozilla::dom::quota::QuotaManager;
 
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -14,16 +14,17 @@
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 
 class nsIDocument;
+class nsIEventTarget;
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 
 class ErrorResult;
 class EventChainPostVisitor;
 
 namespace dom {
@@ -102,16 +103,19 @@ public:
   PRThread*
   OwningThread() const;
 #else
   void
   AssertIsOnOwningThread() const
   { }
 #endif
 
+  nsIEventTarget*
+  EventTarget() const;
+
   const nsString&
   Name() const;
 
   void
   GetName(nsAString& aName) const
   {
     AssertIsOnOwningThread();
 
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -6,16 +6,17 @@
 
 #include "IDBFactory.h"
 
 #include "BackgroundChildImpl.h"
 #include "IDBRequest.h"
 #include "IndexedDatabaseManager.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/SystemGroup.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackground.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozIThirdPartyUtil.h"
@@ -163,16 +164,18 @@ IDBFactory::CreateForWindow(nsPIDOMWindo
 
   nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
 
   RefPtr<IDBFactory> factory = new IDBFactory();
   factory->mPrincipalInfo = Move(principalInfo);
   factory->mWindow = aWindow;
   factory->mTabChild = TabChild::GetFrom(aWindow);
+  factory->mEventTarget =
+    nsGlobalWindow::Cast(aWindow)->EventTargetFor(TaskCategory::Other);
   factory->mInnerWindowID = aWindow->WindowID();
   factory->mPrivateBrowsingMode =
     loadContext && loadContext->UsePrivateBrowsing();
 
   factory.forget(aFactory);
   return NS_OK;
 }
 
@@ -294,16 +297,18 @@ IDBFactory::CreateForJSInternal(JSContex
     *aFactory = nullptr;
     return NS_OK;
   }
 
   RefPtr<IDBFactory> factory = new IDBFactory();
   factory->mPrincipalInfo = aPrincipalInfo.forget();
   factory->mOwningObject = aOwningObject;
   mozilla::HoldJSObjects(factory.get());
+  factory->mEventTarget = NS_IsMainThread() ?
+    SystemGroup::EventTargetFor(TaskCategory::Other) : NS_GetCurrentThread();
   factory->mInnerWindowID = aInnerWindowID;
 
   factory.forget(aFactory);
   return NS_OK;
 }
 
 // static
 bool
@@ -784,16 +789,20 @@ IDBFactory::BackgroundActorCreated(PBack
 {
   MOZ_ASSERT(aBackgroundActor);
   MOZ_ASSERT(!mBackgroundActor);
   MOZ_ASSERT(!mBackgroundActorFailed);
 
   {
     BackgroundFactoryChild* actor = new BackgroundFactoryChild(this);
 
+    // Set EventTarget for the top-level actor.
+    // All child actors created later inherit the same event target.
+    aBackgroundActor->SetEventTargetForActor(actor, EventTarget());
+    MOZ_ASSERT(actor->GetActorEventTarget());
     mBackgroundActor =
       static_cast<BackgroundFactoryChild*>(
         aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor,
                                                                aLoggingInfo));
   }
 
   if (NS_WARN_IF(!mBackgroundActor)) {
     BackgroundActorFailed();
@@ -880,16 +889,19 @@ IDBFactory::InitiateRequest(IDBOpenDBReq
                                       requestedVersion);
 
   if (!mBackgroundActor->SendPBackgroundIDBFactoryRequestConstructor(actor,
                                                                      aParams)) {
     aRequest->DispatchNonTransactionError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
+  MOZ_ASSERT(actor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
+
   return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBFactory)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -13,16 +13,17 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 
+class nsIEventTarget;
 class nsIPrincipal;
 class nsPIDOMWindowInner;
 struct PRThread;
 
 namespace mozilla {
 
 class ErrorResult;
 
@@ -68,16 +69,21 @@ class IDBFactory final
   // This will only be set if the factory belongs to a window in a child
   // process.
   RefPtr<TabChild> mTabChild;
 
   nsTArray<nsAutoPtr<PendingRequestInfo>> mPendingRequests;
 
   indexedDB::BackgroundFactoryChild* mBackgroundActor;
 
+  // A DocGroup-specific EventTarget if created by CreateForWindow().
+  // Otherwise, it must either be set to SystemGroup on main thread or
+  // NS_GetCurrentThread() off main thread.
+  nsCOMPtr<nsIEventTarget> mEventTarget;
+
 #ifdef DEBUG
   PRThread* mOwningThread;
 #endif
 
   uint64_t mInnerWindowID;
 
   bool mBackgroundActorFailed;
   bool mPrivateBrowsingMode;
@@ -113,16 +119,24 @@ public:
   PRThread*
   OwningThread() const;
 #else
   void
   AssertIsOnOwningThread() const
   { }
 #endif
 
+  nsIEventTarget*
+  EventTarget() const
+  {
+    AssertIsOnOwningThread();
+    MOZ_RELEASE_ASSERT(mEventTarget);
+    return mEventTarget;
+  }
+
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
     mBackgroundActor = nullptr;
   }
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -302,16 +302,19 @@ IDBTransaction::StartRequest(IDBRequest*
       SendPBackgroundIDBRequestConstructor(actor, aParams);
   } else {
     MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
 
     mBackgroundActor.mNormalBackgroundActor->
       SendPBackgroundIDBRequestConstructor(actor, aParams);
   }
 
+  MOZ_ASSERT(actor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
+
   // Balanced in BackgroundRequestChild::Recv__delete__().
   OnNewRequest();
 
   return actor;
 }
 
 void
 IDBTransaction::OpenCursor(BackgroundCursorChild* aBackgroundActor,
@@ -328,16 +331,19 @@ IDBTransaction::OpenCursor(BackgroundCur
       SendPBackgroundIDBCursorConstructor(aBackgroundActor, aParams);
   } else {
     MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
 
     mBackgroundActor.mNormalBackgroundActor->
       SendPBackgroundIDBCursorConstructor(aBackgroundActor, aParams);
   }
 
+  MOZ_ASSERT(aBackgroundActor->GetActorEventTarget(),
+    "The event target shall be inherited from its manager actor.");
+
   // Balanced in BackgroundCursorChild::RecvResponse().
   OnNewRequest();
 }
 
 void
 IDBTransaction::RefreshSpec(bool aMayDelete)
 {
   AssertIsOnOwningThread();
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -989,16 +989,21 @@ IndexedDatabaseManager::BlockAndGetFileR
   if (!mBackgroundActor) {
     PBackgroundChild* bgActor = BackgroundChild::GetForCurrentThread();
     if (NS_WARN_IF(!bgActor)) {
       return NS_ERROR_FAILURE;
     }
 
     BackgroundUtilsChild* actor = new BackgroundUtilsChild(this);
 
+    // We don't set event target for BackgroundUtilsChild because:
+    // 1. BackgroundUtilsChild is a singleton.
+    // 2. SendGetFileReferences is a sync operation to be returned asap if unlabeled.
+    // 3. The rest operations like DeleteMe/__delete__ only happens at shutdown.
+    // Hence, we should keep it unlabeled.
     mBackgroundActor =
       static_cast<BackgroundUtilsChild*>(
         bgActor->SendPBackgroundIndexedDBUtilsConstructor(actor));
   }
 
   if (NS_WARN_IF(!mBackgroundActor)) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/indexedDB/ScriptErrorHelper.cpp
+++ b/dom/indexedDB/ScriptErrorHelper.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ScriptErrorHelper.h"
 
 #include "MainThreadUtils.h"
+#include "mozilla/SystemGroup.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 
 namespace {
@@ -205,17 +206,20 @@ ScriptErrorHelper::Dump(const nsAString&
     RefPtr<ScriptErrorRunnable> runnable =
       new ScriptErrorRunnable(aMessage,
                               aFilename,
                               aLineNumber,
                               aColumnNumber,
                               aSeverityFlag,
                               aIsChrome,
                               aInnerWindowID);
-    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
+    MOZ_ALWAYS_SUCCEEDS(
+      SystemGroup::Dispatch("indexedDB::ScriptErrorHelper::Dump",
+                            TaskCategory::Other,
+                            runnable.forget()));
   }
 }
 
 /*static*/ void
 ScriptErrorHelper::DumpLocalizedMessage(const nsACString& aMessageName,
                                         const nsAString& aFilename,
                                         uint32_t aLineNumber,
                                         uint32_t aColumnNumber,
@@ -235,15 +239,18 @@ ScriptErrorHelper::DumpLocalizedMessage(
     RefPtr<ScriptErrorRunnable> runnable =
       new ScriptErrorRunnable(aMessageName,
                               aFilename,
                               aLineNumber,
                               aColumnNumber,
                               aSeverityFlag,
                               aIsChrome,
                               aInnerWindowID);
-    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
+    MOZ_ALWAYS_SUCCEEDS(
+      SystemGroup::Dispatch("indexedDB::ScriptErrorHelper::DumpLocalizedMessage",
+                            TaskCategory::Other,
+                            runnable.forget()));
   }
 }
 
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: IndexedDB")
+
 TEST_DIRS += ['test/extensions']
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
--- a/dom/interfaces/base/moz.build
+++ b/dom/interfaces/base/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'domstubs.idl',
     'nsIBrowser.idl',
     'nsIBrowserDOMWindow.idl',
     'nsIContentPermissionPrompt.idl',
     'nsIContentPrefService.idl',
     'nsIContentPrefService2.idl',
     'nsIContentProcess.idl',
--- a/dom/interfaces/canvas/moz.build
+++ b/dom/interfaces/canvas/moz.build
@@ -1,13 +1,19 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Canvas: 2D")
+
+with Files("nsIDOMWebGLRenderingContext.idl"):
+    BUG_COMPONENT = ("Core", "Canvas: WebGL")
+
 XPIDL_SOURCES += [
     'nsIDOMCanvasRenderingContext2D.idl',
     'nsIDOMWebGLRenderingContext.idl',
 ]
 
 XPIDL_MODULE = 'dom_canvas'
 
--- a/dom/interfaces/core/moz.build
+++ b/dom/interfaces/core/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMAttr.idl',
     'nsIDOMCDATASection.idl',
     'nsIDOMCharacterData.idl',
     'nsIDOMComment.idl',
     'nsIDOMDocument.idl',
     'nsIDOMDocumentFragment.idl',
     'nsIDOMDocumentType.idl',
--- a/dom/interfaces/css/moz.build
+++ b/dom/interfaces/css/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: CSS Object Model")
+
 XPIDL_SOURCES += [
     'nsIDOMCounter.idl',
     'nsIDOMCSSConditionRule.idl',
     'nsIDOMCSSCounterStyleRule.idl',
     'nsIDOMCSSFontFaceRule.idl',
     'nsIDOMCSSFontFeatureValuesRule.idl',
     'nsIDOMCSSGroupingRule.idl',
     'nsIDOMCSSImportRule.idl',
--- a/dom/interfaces/events/moz.build
+++ b/dom/interfaces/events/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Events")
+
 XPIDL_SOURCES += [
     'nsIDOMAnimationEvent.idl',
     'nsIDOMBeforeUnloadEvent.idl',
     'nsIDOMClipboardEvent.idl',
     'nsIDOMCommandEvent.idl',
     'nsIDOMCustomEvent.idl',
     'nsIDOMDataContainerEvent.idl',
     'nsIDOMDataTransfer.idl',
--- a/dom/interfaces/geolocation/moz.build
+++ b/dom/interfaces/geolocation/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
 XPIDL_SOURCES += [
     'nsIDOMGeoGeolocation.idl',
     'nsIDOMGeoPosition.idl',
     'nsIDOMGeoPositionCallback.idl',
     'nsIDOMGeoPositionCoords.idl',
     'nsIDOMGeoPositionError.idl',
     'nsIDOMGeoPositionErrorCallback.idl',
 ]
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMHTMLAnchorElement.idl',
     'nsIDOMHTMLAppletElement.idl',
     'nsIDOMHTMLAreaElement.idl',
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLBodyElement.idl',
     'nsIDOMHTMLButtonElement.idl',
     'nsIDOMHTMLCanvasElement.idl',
--- a/dom/interfaces/json/moz.build
+++ b/dom/interfaces/json/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "JavaScript Engine")
+
 XPIDL_SOURCES += [
     'nsIJSON.idl',
 ]
 
 XPIDL_MODULE = 'dom_json'
 
--- a/dom/interfaces/notification/moz.build
+++ b/dom/interfaces/notification/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsINotificationStorage.idl',
 ]
 
 XPIDL_MODULE = 'dom_notification'
 
--- a/dom/interfaces/offline/moz.build
+++ b/dom/interfaces/offline/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMOfflineResourceList.idl',
 ]
 
 XPIDL_MODULE = 'dom_offline'
 
--- a/dom/interfaces/push/moz.build
+++ b/dom/interfaces/push/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Push Notifications")
+
 XPIDL_SOURCES += [
     'nsIPushErrorReporter.idl',
     'nsIPushNotifier.idl',
     'nsIPushService.idl',
 ]
 
 XPIDL_MODULE = 'dom_push'
--- a/dom/interfaces/range/moz.build
+++ b/dom/interfaces/range/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMRange.idl',
 ]
 
 XPIDL_MODULE = 'dom_range'
 
--- a/dom/interfaces/security/moz.build
+++ b/dom/interfaces/security/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Security")
+
 XPIDL_SOURCES += [
     'nsIContentSecurityManager.idl',
     'nsIContentSecurityPolicy.idl'
 ]
 
 XPIDL_MODULE = 'dom_security'
 
--- a/dom/interfaces/settings/moz.build
+++ b/dom/interfaces/settings/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
 XPIDL_SOURCES += [
     'nsISettingsService.idl',
 ]
 
 XPIDL_MODULE = 'dom_settings'
 
--- a/dom/interfaces/sidebar/moz.build
+++ b/dom/interfaces/sidebar/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIWebContentHandlerRegistrar.idl',
 ]
 
 XPIDL_MODULE = 'dom_sidebar'
 
--- a/dom/interfaces/smil/moz.build
+++ b/dom/interfaces/smil/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "SVG")
+
 XPIDL_SOURCES += [
     'nsIDOMTimeEvent.idl',
 ]
 
 XPIDL_MODULE = 'dom_smil'
 
--- a/dom/interfaces/storage/moz.build
+++ b/dom/interfaces/storage/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMStorage.idl',
     'nsIDOMStorageManager.idl',
 ]
 
 XPIDL_MODULE = 'dom_storage'
--- a/dom/interfaces/stylesheets/moz.build
+++ b/dom/interfaces/stylesheets/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: CSS Object Model")
+
 XPIDL_SOURCES += [
     'nsIDOMMediaList.idl',
     'nsIDOMStyleSheet.idl',
     'nsIDOMStyleSheetList.idl',
 ]
 
 XPIDL_MODULE = 'dom_stylesheets'
 
--- a/dom/interfaces/svg/moz.build
+++ b/dom/interfaces/svg/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "SVG")
+
 XPIDL_SOURCES += [
     'nsIDOMSVGElement.idl',
     'nsIDOMSVGLength.idl',
 ]
 
 XPIDL_MODULE = 'dom_svg'
 
--- a/dom/interfaces/traversal/moz.build
+++ b/dom/interfaces/traversal/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
 XPIDL_SOURCES += [
     'nsIDOMNodeFilter.idl',
     'nsIDOMNodeIterator.idl',
     'nsIDOMTreeWalker.idl',
 ]
 
 XPIDL_MODULE = 'dom_traversal'
 
--- a/dom/interfaces/xbl/moz.build
+++ b/dom/interfaces/xbl/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "XBL")
+
 XPIDL_SOURCES += [
     'nsIDOMDocumentXBL.idl',
 ]
 
 XPIDL_MODULE = 'dom_xbl'
 
--- a/dom/interfaces/xpath/moz.build
+++ b/dom/interfaces/xpath/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "XSLT")
+
 XPIDL_SOURCES += [
     'nsIDOMXPathEvaluator.idl',
     'nsIDOMXPathResult.idl',
 ]
 
 XPIDL_MODULE = 'dom_xpath'
 
--- a/dom/interfaces/xul/moz.build
+++ b/dom/interfaces/xul/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "XUL")
+
 XPIDL_SOURCES += [
     'nsIDOMXULButtonElement.idl',
     'nsIDOMXULCheckboxElement.idl',
     'nsIDOMXULCommandDispatcher.idl',
     'nsIDOMXULCommandEvent.idl',
     'nsIDOMXULContainerElement.idl',
     'nsIDOMXULControlElement.idl',
     'nsIDOMXULDescriptionElement.idl',
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Content Processes")
+
 XPIDL_SOURCES += [
     'nsIHangReport.idl',
 ]
 
 XPIDL_MODULE = 'dom'
 
 EXPORTS.mozilla.dom.ipc += [
     'IdType.h',
--- a/dom/json/moz.build
+++ b/dom/json/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "JavaScript Engine")
+
 EXPORTS += [
     'nsJSON.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsJSON.cpp',
 ]
 
--- a/dom/jsurl/moz.build
+++ b/dom/jsurl/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Document Navigation")
+
 EXPORTS += [
     'nsJSProtocolHandler.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsJSProtocolHandler.cpp',
 ]
 
--- a/dom/locales/moz.build
+++ b/dom/locales/moz.build
@@ -1,7 +1,61 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("en-US/chrome/accessibility/**"):
+    BUG_COMPONENT = ("Core", "Disability Access APIs")
+
+with Files("en-US/chrome/dom/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("en-US/chrome/layout/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("en-US/chrome/layout/css.properties"):
+    BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
+
+with Files("en-US/chrome/layout/htmlparser.properties"):
+    BUG_COMPONENT = ("Core", "HTML: Parser")
+
+with Files("en-US/chrome/layout/layout_errors.properties"):
+    BUG_COMPONENT = ("Core", "DOM: Animation")
+
+with Files("en-US/chrome/layout/MediaDocument.properties"):
+    BUG_COMPONENT = ("Core", "Layout: Images")
+
+with Files("en-US/chrome/layout/printing.properties"):
+    BUG_COMPONENT = ("Core", "Printing: Output")
+
+with Files("en-US/chrome/layout/xbl.properties"):
+    BUG_COMPONENT = ("Core", "XBL")
+
+with Files("en-US/chrome/layout/xmlparser.properties"):
+    BUG_COMPONENT = ("Core", "XML")
+
+with Files("en-US/chrome/layout/xul.properties"):
+    BUG_COMPONENT = ("Core", "XUL")
+
+with Files("en-US/chrome/mathml/**"):
+    BUG_COMPONENT = ("Core", "MathML")
+
+with Files("en-US/chrome/security/**"):
+    BUG_COMPONENT = ("Core", "Security")
+
+with Files("en-US/chrome/svg/**"):
+    BUG_COMPONENT = ("Core", "SVG")
+
+with Files("en-US/chrome/xml/**"):
+    BUG_COMPONENT = ("Core", "XML")
+
+with Files("en-US/chrome/xslt/**"):
+    BUG_COMPONENT = ("Core", "XSLT")
+
+with Files("en-US/chrome/plugins.properties"):
+    BUG_COMPONENT = ("Core", "Plug-ins")
+
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/dom/manifest/moz.build
+++ b/dom/manifest/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXTRA_JS_MODULES += [
     'ImageObjectProcessor.jsm',
     'Manifest.jsm',
     'ManifestFinder.jsm',
     'ManifestIcons.jsm',
     'ManifestObtainer.jsm',
     'ManifestProcessor.jsm',
     'ValueExtractor.jsm',
--- a/dom/mathml/moz.build
+++ b/dom/mathml/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "MathML")
+
 UNIFIED_SOURCES += [
     'nsMathMLElement.cpp',
     'nsMathMLElementFactory.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/media/webrtc/PeerIdentity.h
+++ b/dom/media/webrtc/PeerIdentity.h
@@ -2,21 +2,17 @@
   * vim: sw=2 ts=2 sts=2 expandtab
   * This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef PeerIdentity_h
 #define PeerIdentity_h
 
-#ifdef MOZILLA_INTERNAL_API
 #include "nsString.h"
-#else
-#include "nsStringAPI.h"
-#endif
 
 template <class T> class nsCOMPtr;
 class nsIIDNService;
 
 namespace mozilla {
 
 /**
  * This class implements the identifier used in WebRTC identity.  Peers are
--- a/dom/messagechannel/moz.build
+++ b/dom/messagechannel/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 TEST_DIRS += ['tests']
 
 EXPORTS.mozilla.dom += [
     'MessageChannel.h',
     'MessagePort.h',
     'MessagePortChild.h',
     'MessagePortParent.h',
 ]
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -1,14 +1,21 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+# interfaces/*/ are annotated per directory, this is for new files
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("plugins/**"):
+    BUG_COMPONENT = ("Core", "Plug-ins")
+
 JAR_MANIFESTS += ['jar.mn']
 
 interfaces = [
     'base',
     'canvas',
     'core',
     'html',
     'events',
--- a/dom/offline/moz.build
+++ b/dom/offline/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Networking")
+
 EXPORTS += [
     'nsDOMOfflineResourceList.h',
 ]
 UNIFIED_SOURCES += [
     'nsDOMOfflineResourceList.cpp',
 ]
 
 LOCAL_INCLUDES += [
--- a/dom/performance/moz.build
+++ b/dom/performance/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'Performance.h',
     'PerformanceEntry.h',
     'PerformanceMark.h',
     'PerformanceMeasure.h',
     'PerformanceNavigation.h',
     'PerformanceObserver.h',
     'PerformanceObserverEntryList.h',
--- a/dom/permission/moz.build
+++ b/dom/permission/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'Permissions.h',
     'PermissionStatus.h',
 ]
 
 UNIFIED_SOURCES += [
     'PermissionObserver.cpp',
     'Permissions.cpp',
--- a/dom/power/moz.build
+++ b/dom/power/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsIDOMWakeLockListener.idl',
     'nsIPowerManagerService.idl',
 ]
 
 XPIDL_MODULE = 'dom_power'
 
 EXPORTS.mozilla.dom += [
--- a/dom/presentation/moz.build
+++ b/dom/presentation/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 DIRS += ['interfaces', 'provider']
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
 
 EXPORTS.mozilla.dom += [
     'DCPresentationChannelDescription.h',
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'Promise.h',
     'PromiseDebugging.h',
     'PromiseNativeHandler.h',
     'PromiseWorkerProxy.h',
 ]
 
 UNIFIED_SOURCES += [
--- a/dom/push/moz.build
+++ b/dom/push/moz.build
@@ -1,13 +1,16 @@
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Push Notifications")
+
 EXTRA_COMPONENTS += [
     'Push.js',
     'Push.manifest',
     'PushComponents.js',
 ]
 
 EXTRA_JS_MODULES += [
     'PushCrypto.jsm',
--- a/dom/quota/moz.build
+++ b/dom/quota/moz.build
@@ -1,14 +1,18 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Quota Manager")
+
 XPIDL_SOURCES += [
     'nsIQuotaCallbacks.idl',
     'nsIQuotaManagerService.idl',
     'nsIQuotaRequests.idl',
 ]
 
 XPIDL_MODULE = 'dom_quota'
 
--- a/dom/secureelement/moz.build
+++ b/dom/secureelement/moz.build
@@ -1,15 +1,19 @@
 # vim: set filetype=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/.
 #
 # Copyright © 2014 Deutsche Telekom, Inc.
 
+# All of this seems to be FirefoxOS::NFC
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
 if CONFIG['MOZ_SECUREELEMENT']:
     EXTRA_COMPONENTS += [
         'DOMSecureElement.js',
         'DOMSecureElement.manifest',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_SECUREELEMENT']:
     EXTRA_COMPONENTS += [
--- a/dom/smil/moz.build
+++ b/dom/smil/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "SVG")
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'nsISMILAttr.h',
     'nsISMILType.h',
     'nsSMILAnimationController.h',
     'nsSMILAnimationFunction.h',
     'nsSMILCompositorTable.h',
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "SVG")
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'nsSVGClass.h',
     'nsSVGElement.h',
     'nsSVGFeatures.h',
     'SVGAttrValueWrapper.h',
     'SVGContentUtils.h',
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -1,14 +1,49 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+# This picks up *hapticfeedback* which is graveyard
+# This picks up gonk/* which is also not supported?
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("*OSFile*"):
+    BUG_COMPONENT = ("Toolkit", "OS.File")
+
+with Files("*ocationProvider*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("windows/*LocationProvider*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("mac/*LocationProvider*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("linux/*LocationProvider*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("android/*LocationProvider*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("tests/chrome.ini"):
+    BUG_COMPONENT = ("Toolkit", "OS.File")
+
+with Files("tests/*constants*"):
+    BUG_COMPONENT = ("Toolkit", "OS.File")
+
+with Files("tests/mochitest.ini"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
+with Files("tests/*1197901*"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
 toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
 if toolkit == 'windows':
     DIRS += ['windows']
 elif toolkit == 'cocoa':
     DIRS += ['mac']
 elif toolkit == 'android':
     DIRS += ['android']
--- a/dom/tests/mochitest/fetch/test_request.js
+++ b/dom/tests/mochitest/fetch/test_request.js
@@ -147,22 +147,19 @@ function testHeaderGuard() {
   ok(r1.headers.has("Non-Simple-Header"), "Default Request header should have guard request and allow setting non-simple header.");
 
   var r2 = new Request("", { mode: "no-cors", headers: headers });
   ok(!r2.headers.has("Cookie"), "no-cors Request header should have guard request-no-cors and prevent setting non-simple header.");
   ok(!r2.headers.has("Non-Simple-Header"), "no-cors Request header should have guard request-no-cors and prevent setting non-simple header.");
 }
 
 function testMode() {
-  try {
-    var req = new Request("http://example.com", {mode: "navigate"});
-    ok(false, "Creating a Request with navigate RequestMode should throw a TypeError");
-  } catch(e) {
-    is(e.name, "TypeError", "Creating a Request with navigate RequestMode should throw a TypeError");
-  }
+  var req = new Request("http://example.com", {mode: "navigate"});
+  ok(true, "Creating a Request with navigate RequestMode should not throw.");
+  is(req.mode, "same-origin", "Request mode becomes same-origin");
 }
 
 function testMethod() {
   // These get normalized.
   var allowed = ["delete", "get", "head", "options", "post", "put" ];
   for (var i = 0; i < allowed.length; ++i) {
     try {
       var r = new Request("", { method: allowed[i] });
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -749,17 +749,17 @@ var interfaceNamesInGlobalScope =
     "Permissions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PermissionStatus",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Plugin",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PluginArray",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PointerEvent", nightly: true, desktop: true, disabled: true},
+    {name: "PointerEvent", nightly: true, desktop: true, windows: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopStateEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopupBlockedEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PopupBoxObject", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationDeviceInfoManager",
--- a/dom/tests/moz.build
+++ b/dom/tests/moz.build
@@ -1,14 +1,158 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("browser/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("browser/*onsole*"):
+    BUG_COMPONENT = ("Firefox", "Developer Tools")
+
+with Files("browser/*autofocus*"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+with Files("browser/*unload*"):
+    BUG_COMPONENT = ("Core", "DOM: Events")
+
+with Files("browser/*1238427*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("browser/*Geolocation*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("browser/*geo_*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("browser/browser_cancel_keydown_keypress_event.js"):
+    BUG_COMPONENT = ("Core", "Event Handling")
+
+with Files("browser/*local*"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("browser/*prerender*"):
+    BUG_COMPONENT = ("Core", "Document Navigation")
+
+with Files("browser/browser_test_focus_after_modal_state.js"):
+    BUG_COMPONENT = ("Core", "Event Handling")
+
+with Files("mochitest/ajax/**"):
+    BUG_COMPONENT = ("Testing", "Mochitest")
+
+with Files("mochitest/ajax/offline/**"):
+    BUG_COMPONENT = ("Core", "Networking: Cache")
+
+with Files("mochitest/beacon/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+# big mix of components here
+with Files("mochitest/bugs/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+# TODO: big mix of components here
+with Files("mochitest/chrome/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/crypto/**"):
+    BUG_COMPONENT = ("Core", "DOM: Security")
+
+with Files("mochitest/dom-level0/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/dom-level1-core/**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+with Files("mochitest/dom-level2-core/**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+with Files("mochitest/dom-level2-html/**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+with Files("mochitest/fetch/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/gamepad/**"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
+# TODO: big mix of components here
+with Files("mochitest/general/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/geolocation/**"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("mochitest/localstorage/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/notification/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/orientation/**"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
+with Files("mochitest/orientation/*507902*"):
+    BUG_COMPONENT = ("Core", "Layout: Images")
+
+with Files("mochitest/pointerlock/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/sessionstorage/**"):
+    BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+with Files("mochitest/storageevent/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/webcomponents/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("mochitest/whatwg/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("reftest/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("reftest/*456008*"):
+    BUG_COMPONENT = ("Core", "XML")
+
+with Files("reftest/*439965*"):
+    BUG_COMPONENT = ("Core", "Editor")
+
+with Files("reftest/*427779*"):
+    BUG_COMPONENT = ("Core", "XML")
+
+with Files("reftest/*559996*"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("reftest/*591981*"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("reftest/*592366*"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("reftest/*798068*"):
+    BUG_COMPONENT = ("Core", "Layout")
+
+with Files("reftest/xml-stylesheet/**"):
+    BUG_COMPONENT = ("Core", "XSLT")
+
+with Files("unit/**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
+with Files("unit/*geolocation*"):
+    BUG_COMPONENT = ("Core", "Geolocation")
+
+with Files("unit/test_bug465752.js"):
+    BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
+
+with Files("unit/test_PromiseDebugging.js"):
+    BUG_COMPONENT = ("Core", "XPConnect")
+
 MOCHITEST_MANIFESTS += [
     'mochitest/ajax/jquery/mochitest.ini',
     'mochitest/ajax/mochikit/mochitest.ini',
     'mochitest/ajax/offline/mochitest.ini',
     'mochitest/ajax/prototype/mochitest.ini',
     'mochitest/ajax/scriptaculous/mochitest.ini',
     'mochitest/beacon/mochitest.ini',
     'mochitest/bugs/mochitest.ini',
--- a/dom/time/moz.build
+++ b/dom/time/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+
 XPIDL_SOURCES += [
     'nsITimeService.idl',
 ]
 
 XPIDL_MODULE = 'dom_time'
 
 EXPORTS.mozilla.dom.time += [
     'DateCacheCleaner.h',
--- a/dom/url/moz.build
+++ b/dom/url/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'URL.h',
     'URLSearchParams.h',
 ]
 
 UNIFIED_SOURCES += [
     'URL.cpp',
     'URLSearchParams.cpp',
--- a/dom/webbrowserpersist/moz.build
+++ b/dom/webbrowserpersist/moz.build
@@ -1,14 +1,18 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+# moved from embedding/components/webbrowserpersist Jan 13, 2017
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 XPIDL_SOURCES += [
     'nsCWebBrowserPersist.idl',
     'nsIWebBrowserPersist.idl',
     'nsIWebBrowserPersistable.idl',
     'nsIWebBrowserPersistDocument.idl',
 ]
 
 XPIDL_MODULE = 'webbrowserpersist'
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -188,24 +188,27 @@ class MatchAllRunnable final : public Ru
 
       promise->MaybeResolve(ret);
       mPromiseProxy->CleanUp();
       return true;
     }
   };
 
   RefPtr<PromiseWorkerProxy> mPromiseProxy;
-  nsCString mScope;
-  bool mIncludeUncontrolled;
+  const nsCString mScope;
+  const uint64_t mServiceWorkerID;
+  const bool mIncludeUncontrolled;
 public:
   MatchAllRunnable(PromiseWorkerProxy* aPromiseProxy,
                    const nsCString& aScope,
+                   uint64_t aServiceWorkerID,
                    bool aIncludeUncontrolled)
     : mPromiseProxy(aPromiseProxy),
       mScope(aScope),
+      mServiceWorkerID(aServiceWorkerID),
       mIncludeUncontrolled(aIncludeUncontrolled)
   {
     MOZ_ASSERT(mPromiseProxy);
   }
 
   NS_IMETHOD
   Run() override
   {
@@ -215,17 +218,18 @@ public:
     if (mPromiseProxy->CleanedUp()) {
       return NS_OK;
     }
 
     nsTArray<ServiceWorkerClientInfo> result;
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (swm) {
       swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(),
-                         mScope, mIncludeUncontrolled, result);
+                         mScope, mServiceWorkerID, mIncludeUncontrolled,
+                         result);
     }
     RefPtr<ResolvePromiseWorkerRunnable> r =
       new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
                                        mPromiseProxy, result);
 
     r->Dispatch();
     return NS_OK;
   }
@@ -826,16 +830,17 @@ ServiceWorkerClients::MatchAll(const Cli
   if (!promiseProxy) {
     promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     return promise.forget();
   }
 
   RefPtr<MatchAllRunnable> r =
     new MatchAllRunnable(promiseProxy,
                          NS_ConvertUTF16toUTF8(scope),
+                         workerPrivate->ServiceWorkerID(),
                          aOptions.mIncludeUncontrolled);
   MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 ServiceWorkerClients::OpenWindow(const nsAString& aUrl,
                                  ErrorResult& aRv)
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -2944,16 +2944,17 @@ ServiceWorkerManager::GetClient(nsIPrinc
 
   clientInfo.reset(new ServiceWorkerClientInfo(doc));
   return clientInfo;
 }
 
 void
 ServiceWorkerManager::GetAllClients(nsIPrincipal* aPrincipal,
                                     const nsCString& aScope,
+                                    uint64_t aServiceWorkerID,
                                     bool aIncludeUncontrolled,
                                     nsTArray<ServiceWorkerClientInfo>& aDocuments)
 {
   MOZ_ASSERT(aPrincipal);
 
   RefPtr<ServiceWorkerRegistrationInfo> registration =
     GetRegistration(aPrincipal, aScope);
 
@@ -2999,20 +3000,23 @@ ServiceWorkerManager::GetAllClients(nsIP
     // setting is enabled.
     if (!doc->GetWindow()->GetServiceWorkersTestingEnabled() &&
         !Preferences::GetBool("dom.serviceWorkers.testing.enabled") &&
         !IsFromAuthenticatedOrigin(doc)) {
       continue;
     }
 
     // If we are only returning controlled Clients then skip any documents
-    // that are for different registrations.
+    // that are for different registrations.  We also skip service workers
+    // that don't match the ID of our calling service worker.  We should
+    // only return Clients controlled by that precise service worker.
     if (!aIncludeUncontrolled) {
       ServiceWorkerRegistrationInfo* reg = mControlledDocuments.GetWeak(doc);
-      if (!reg || reg->mScope != registration->mScope) {
+      if (!reg || reg->mScope != aScope || !reg->GetActive() ||
+          reg->GetActive()->ID() != aServiceWorkerID) {
         continue;
       }
     }
 
     if (!aIncludeUncontrolled && !mControlledDocuments.Contains(doc)) {
       continue;
     }
 
--- a/dom/workers/ServiceWorkerManager.h
+++ b/dom/workers/ServiceWorkerManager.h
@@ -267,16 +267,17 @@ public:
   UniquePtr<ServiceWorkerClientInfo>
   GetClient(nsIPrincipal* aPrincipal,
             const nsAString& aClientId,
             ErrorResult& aRv);
 
   void
   GetAllClients(nsIPrincipal* aPrincipal,
                 const nsCString& aScope,
+                uint64_t aServiceWorkerID,
                 bool aIncludeUncontrolled,
                 nsTArray<ServiceWorkerClientInfo>& aDocuments);
 
   void
   MaybeClaimClient(nsIDocument* aDocument,
                    ServiceWorkerRegistrationInfo* aWorkerRegistration);
 
   nsresult
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM: Workers")
+
 # Public stuff.
 EXPORTS.mozilla.dom += [
     'FileReaderSync.h',
     'ServiceWorkerCommon.h',
     'ServiceWorkerContainer.h',
     'ServiceWorkerEvents.h',
     'ServiceWorkerRegistrar.h',
     'ServiceWorkerRegistration.h',
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/claim_fetch_worker.js
+++ /dev/null
@@ -1,12 +0,0 @@
-onfetch = function(e) {
-  if (e.request.url.indexOf("service_worker_controlled") >= 0) {
-    // pass through
-    e.respondWith(fetch(e.request));
-  } else {
-    e.respondWith(new Response("Fetch was intercepted"));
-  }
-}
-
-onmessage = function(e) {
-  clients.claim();
-}
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js
+++ b/dom/workers/test/serviceworkers/fetch_event_worker.js
@@ -143,38 +143,31 @@ onfetch = function(ev) {
         headers : {
           "Content-Type": "text/html"
         }
       })
     ));
   }
 
   else if (ev.request.url.includes("navigate.html")) {
-    var navigateModeCorrectlyChecked = false;
     var requests = [ // should not throw
       new Request(ev.request),
       new Request(ev.request, undefined),
       new Request(ev.request, null),
       new Request(ev.request, {}),
       new Request(ev.request, {someUnrelatedProperty: 42}),
+      new Request(ev.request, {method: "GET"}),
     ];
-    try {
-      var request3 = new Request(ev.request, {method: "GET"}); // should throw
-    } catch(e) {
-      navigateModeCorrectlyChecked = requests[0].mode == "navigate";
-    }
-    if (navigateModeCorrectlyChecked) {
-      ev.respondWith(Promise.resolve(
-        new Response("<script>window.frameElement.test_result = true;</script>", {
-          headers : {
-            "Content-Type": "text/html"
-          }
-        })
-      ));
-    }
+    ev.respondWith(Promise.resolve(
+      new Response("<script>window.frameElement.test_result = true;</script>", {
+        headers : {
+          "Content-Type": "text/html"
+        }
+      })
+    ));
   }
 
   else if (ev.request.url.includes("nonexistent_worker_script.js")) {
     ev.respondWith(Promise.resolve(
       new Response("postMessage('worker-intercept-success')", {})
     ));
   }
 
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -157,17 +157,16 @@ support-files =
   swa/worker_scope_too_deep.js
   swa/worker_scope_too_deep.js^headers^
   swa/worker_scope_too_narrow.js
   swa/worker_scope_too_narrow.js^headers^
   claim_oninstall_worker.js
   claim_worker_1.js
   claim_worker_2.js
   claim_clients/client.html
-  claim_fetch_worker.js
   force_refresh_worker.js
   sw_clients/refresher.html
   sw_clients/refresher_compressed.html
   sw_clients/refresher_compressed.html^headers^
   sw_clients/refresher_cached.html
   sw_clients/refresher_cached_compressed.html
   sw_clients/refresher_cached_compressed.html^headers^
   strict_mode_warning.js
@@ -213,17 +212,16 @@ support-files =
   sharedWorker_fetch.js
   async_waituntil_worker.js
   lazy_worker.js
   nofetch_handler_worker.js
 
 [test_bug1151916.html]
 [test_bug1240436.html]
 [test_claim.html]
-[test_claim_fetch.html]
 [test_claim_oninstall.html]
 [test_controller.html]
 [test_cross_origin_url_after_redirect.html]
 [test_csp_upgrade-insecure_intercept.html]
 [test_empty_serviceworker.html]
 [test_error_reporting.html]
 [test_escapedSlashes.html]
 [test_eval_allowed.html]
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/test_claim_fetch.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Bug 1130684 - Test fetch events are intercepted after claim </title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-  <a ping="ping" href="fetch.txt">link</a>
-</div>
-<pre id="test"></pre>
-<script class="testbody" type="text/javascript">
-  var registration;
-
-  function register() {
-    return navigator.serviceWorker.register("claim_fetch_worker.js",
-                                            { scope: "./" })
-      .then((swr) => registration = swr);
-  }
-
-  function unregister() {
-    return registration.unregister().then(function(result) {
-      ok(result, "Unregister should return true.");
-    });
-  }
-
-  function createClient() {
-    var p = new Promise(function(res, rej){
-      window.onmessage = function(e) {
-        if(e.data === "READY") {
-          res();
-        }
-      }
-    });
-
-    var content = document.getElementById("content");
-    ok(content, "Parent exists.");
-
-    iframe = document.createElement("iframe");
-    iframe.setAttribute('src', "sw_clients/service_worker_controlled.html");
-    content.appendChild(iframe);
-
-    return p;
-  }
-
-  function testFetch(before) {
-    return fetch("fetch/real-file.txt").then(function(res) {
-      ok(res.ok, "Response should be valid.");
-      return res.text().then(function(body) {
-        if (before) {
-          ok(body !== "Fetch was intercepted", "Fetch events should not be intercepted.");
-        } else {
-          ok(body === "Fetch was intercepted", "Fetch events should be intercepted.");
-        }
-      });
-    });
-  }
-
-  function claimThisPage() {
-    ok(registration.active, "Worker is active.");
-    var p = new Promise(function (res, rej) {
-      navigator.serviceWorker.oncontrollerchange = res;
-    });
-
-    registration.active.postMessage("Claim");
-
-    return p;
-  }
-
-  function runTest() {
-    register()
-      .then(createClient)
-      .then(testFetch.bind(this, true))
-      .then(claimThisPage)
-      .then(testFetch.bind(this, false))
-      .then(unregister)
-      .catch(function(e) {
-        ok(false, "Some test failed with error " + e);
-      }).then(SimpleTest.finish);
-  }
-
-  SimpleTest.waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({"set": [
-    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
-    ["dom.serviceWorkers.enabled", true],
-    ["dom.serviceWorkers.testing.enabled", true]
-  ]}, runTest);
-</script>
-</pre>
-</body>
-</html>
-
--- a/dom/worklet/moz.build
+++ b/dom/worklet/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
+with Files("**"):
+    BUG_COMPONENT = ("Core", "DOM")
+
 EXPORTS.mozilla.dom += [
     'AudioWorkletGlobalScope.h',
     'PaintWorkletGlobalScope.h',
     'Worklet.h',
     'WorkletGlobalScope.h',
 ]
 
 UNIFIED_SOURCES += [
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/NEWS
@@ -0,0 +1,1593 @@
+Overview of changes leading to 1.4.3
+Saturday, February 25, 2017
+====================================
+
+- Route Adlam script to Arabic shaper.
+- Misc fixes.
+- New API:
+  hb_font_set_face()
+- Deprecate API:
+  hb_graphite2_font_get_gr_font()
+
+
+Overview of changes leading to 1.4.2
+Monday, January 23, 2017
+====================================
+
+- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR.
+- hb-shape and hb-view now accept --variations.
+- New API:
+
+hb_variation_t
+hb_variation_from_string()
+hb_variation_to_string()
+
+hb_font_set_variations()
+hb_font_set_var_coords_design()
+hb_font_get_var_coords_normalized()
+
+hb-ot-var.h:
+hb_ot_var_axis_t
+hb_ot_var_has_data()
+hb_ot_var_get_axis_count()
+hb_ot_var_get_axes()
+hb_ot_var_find_axis()
+hb_ot_var_normalize_variations()
+hb_ot_var_normalize_coords()
+
+- MVAR to be implemented later.  Access to named instances to be
+  implemented later as well.
+
+- Misc fixes.
+
+
+Overview of changes leading to 1.4.1
+Thursday, January 5, 2017
+====================================
+
+- Always build and use UCDN for Unicode data by default.
+  Reduces dependence on version of Unicode data in glib,
+  specially in the Windows bundles we are shipping, which
+  have very old glib.
+
+
+Overview of changes leading to 1.4.0
+Thursday, January 5, 2017
+====================================
+
+- Merged "OpenType GX" branch which adds core of support for
+  OpenType 1.8 Font Variations.  To that extent, the relevant
+  new API is:
+
+New API:
+hb_font_set_var_coords_normalized()
+
+  with supporting API:
+
+New API:
+HB_OT_LAYOUT_NO_VARIATIONS_INDEX
+hb_ot_layout_table_find_feature_variations()
+hb_ot_layout_feature_with_variations_get_lookups()
+hb_shape_plan_create2()
+hb_shape_plan_create_cached2()
+
+  Currently variations in GSUB/GPOS/GDEF are fully supported,
+  and no other tables are supported.  In particular, fvar/avar
+  are NOT supported, hence the hb_font_set_var_coords_normalized()
+  taking normalized coordinates.  API to take design coordinates
+  will be added in the future.
+
+  HVAR/VVAR/MVAR support will also be added to hb-ot-font in the
+  future.
+
+- Fix regression in GDEF glyph class processing.
+- Add decompositions for Chakma, Limbu, and Balinese in USE shaper.
+- Misc fixes.
+
+
+Overview of changes leading to 1.3.4
+Monday, December 5, 2016
+====================================
+
+- Fix vertical glyph origin in hb-ot-font.
+- Implement CBDT/CBLC color font glyph extents in hb-ot-font.
+
+
+Overview of changes leading to 1.3.3
+Wednesday, September 28, 2016
+====================================
+
+- Implement parsing of OpenType MATH table.
+New API:
+HB_OT_TAG_MATH
+HB_OT_MATH_SCRIPT
+hb_ot_math_constant_t
+hb_ot_math_kern_t
+hb_ot_math_glyph_variant_t
+hb_ot_math_glyph_part_flags_t
+hb_ot_math_glyph_part_t
+hb_ot_math_has_data
+hb_ot_math_get_constant
+hb_ot_math_get_glyph_italics_correction
+hb_ot_math_get_glyph_top_accent_attachment
+hb_ot_math_get_glyph_kerning
+hb_ot_math_is_glyph_extended_shape
+hb_ot_math_get_glyph_variants
+hb_ot_math_get_min_connector_overlap
+hb_ot_math_get_glyph_assembly
+
+
+Overview of changes leading to 1.3.2
+Wednesday, September 27, 2016
+====================================
+
+- Fix build of hb-coretext on older OS X versions.
+
+
+Overview of changes leading to 1.3.1
+Wednesday, September 7, 2016
+====================================
+
+- Blacklist bad GDEF of more fonts (Padauk).
+- More CoreText backend crash fixes with OS X 10.9.5.
+- Misc fixes.
+
+
+Overview of changes leading to 1.3.0
+Thursday, July 21, 2016
+====================================
+
+- Update to Unicode 9.0.0
+- Move Javanese from Indic shaper to Universal Shaping Engine.
+- Allow MultipleSubst to delete a glyph (matching Windows engine).
+- Update Universal Shaping Engine to latest draft from Microsoft.
+- DirectWrite backend improvements.  Note: this backend is for testing ONLY.
+- CoreText backend improvements with unreachable fonts.
+- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font.
+- Blacklist bad GDEF of more fonts (Tahoma & others).
+- Misc fixes.
+
+
+Overview of changes leading to 1.2.7
+Monday, May 2, 2016
+====================================
+
+- Blacklist another version of Times New Roman (Bold) Italic from Windows 7.
+- Fix Mongolian Free Variation Selectors shaping with certain fonts.
+- Fix Tibetan shorthand contractions shaping.
+- Improved list of language tag mappings.
+- Unbreak build on Windows CE.
+- Make 'glyf' table loading lazy in hb-ot-font.
+
+
+Overview of changes leading to 1.2.6
+Friday, April 8, 2016
+====================================
+
+- Blacklist GDEF table of another set of Times New Roman (Bold) Italic.
+- DirectWrite backend improvements.  Note: DirectWrite backend is
+  exclusively for our internal testing and should NOT be used in any
+  production system whatsoever.
+
+
+Overview of changes leading to 1.2.5
+Monday, April 4, 2016
+====================================
+
+- Fix GDEF mark-filtering-set, which was broken in 1.2.3.
+
+
+Overview of changes leading to 1.2.4
+Thursday, March 17, 2016
+====================================
+
+- Synthesize GDEF glyph class for any glyph that does not have one in GDEF.
+  I really hope we don't discover broken fonts that shape badly with this
+  change.
+- Misc build and other minor fixes.
+- API changes:
+  - Added HB_NDEBUG.  It's fine for production systems to define this to
+    disable high-overhead debugging checks.  However, I also reduced the
+    overhead of those checks, so it's a non-issue right now.  You can
+    forget it.  Just not defining anything at all is fine.
+
+
+Overview of changes leading to 1.2.3
+Thursday, February 25, 2016
+====================================
+
+- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic,
+  due to bug in glyph class of ASCII double-quote character.  This should
+  address "regression" introduced in 1.2.0 when we switched mark zeroing
+  in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
+  This fourth release in a week should finally stablize things...
+
+- hb-ot-font's get_glyph() implementation saw some optimizations.  Though,
+  might be really hard to measure in real-world situations.
+
+- Also, two rather small API changes:
+
+We now disable some time-consuming internal bookkeeping if built with NDEBUG
+defined.  This is a first time that we use NDEBUG to disable debug code.  If
+there exist production systems that do NOT want to enable NDEBUG, please let
+me know and I'll add HB_NDEBUG.
+
+Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph()
+
+New API:
+- hb_font_get_nominal_glyph_func_t
+- hb_font_get_variation_glyph_func_t
+- hb_font_funcs_set_nominal_glyph_func()
+- hb_font_funcs_set_variation_glyph_func()
+- hb_font_get_nominal_glyph()
+- hb_font_get_variation_glyph()
+
+Deprecated API:
+- hb_font_get_glyph_func_t
+- hb_font_funcs_set_glyph_func()
+
+Clients that implement their own font-funcs are encouraged to replace
+their get_glyph() implementation with a get_nominal_glyph() and
+get_variation_glyph() pair.  The variation version can assume that
+variation_selector argument is not zero.  Old (deprecated) functions
+will continue working indefinitely using internal gymnastics; it is
+just more efficient to use the new functions.
+
+
+Overview of changes leading to 1.2.2
+Wednesday, February 24, 2016
+====================================
+
+- Fix regression with mark positioning with fonts that have
+  non-zero mark advances.  This was introduced in 1.2.0 while
+  trying to make mark and cursive attachments to work together.
+  I have partially reverted that, so this version is much more
+  like what we had before.  All clients who updated to 1.2.0
+  should update to this version.
+
+
+Overview of changes leading to 1.2.1
+Tuesday, February 23, 2016
+====================================
+
+- CoreText: Fix bug with wrong scale if font scale was changed later.
+  https://github.com/libass/libass/issues/212
+- CoreText: Drastically speed up font initialization.
+- CoreText: Fix tiny leak.
+- Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
+  https://github.com/behdad/harfbuzz/issues/217
+- Add test/shaping/README.md about how to add tests to the suite.
+
+
+Overview of changes leading to 1.2.0
+Friday, February 19, 2016
+====================================
+
+- Fix various issues (hangs mostly) in case of memory allocation failure.
+- Change mark zeroing types of most shapers from BY_UNICODE_LATE to
+  BY_GDEF_LATE.  This seems to be what Uniscribe does.
+- Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY.  That's
+  what Windows does.
+- Allow GPOS cursive connection on marks, and fix the interaction with
+  mark attachment.  This work resulted in some changes to how mark
+  attachments work.  See:
+  https://github.com/behdad/harfbuzz/issues/211
+  https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
+- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
+- Add nmake-based build system for Windows.
+- Minor speedup.
+- Misc. improvements.
+
+
+Overview of changes leading to 1.1.3
+Monday, January 11, 2016
+====================================
+
+- Ported Indic shaper to Unicode 8.0 data.
+- Universal Shaping Engine fixes.
+- Speed up CoreText shaper when font fallback happens in CoreText.
+- Documentation improvements, thanks to Khaled Hosny.
+- Very rough directwrite shaper for testing, thanks to Ebrahim Byagowi.
+- Misc bug fixes.
+- New API:
+
+  * Font extents:
+      hb_font_extents_t
+      hb_font_get_font_extents_func_t
+      hb_font_get_font_h_extents_func_t
+      hb_font_get_font_v_extents_func_t
+      hb_font_funcs_set_font_h_extents_func
+      hb_font_funcs_set_font_v_extents_func
+      hb_font_get_h_extents
+      hb_font_get_v_extents
+      hb_font_get_extents_for_direction
+
+  * Buffer message (aka debug):
+      hb_buffer_message_func_t
+      hb_buffer_set_message_func()
+    Actual message protocol to be fleshed out later.
+
+
+Overview of changes leading to 1.1.2
+Wednesday, November 26, 2015
+====================================
+
+- Fix badly-broken fallback shaper that affected terminology.
+  https://github.com/behdad/harfbuzz/issues/187
+- Fix y_scaling in Graphite shaper.
+- API changes:
+  * An unset glyph_h_origin() function in font-funcs now (sensibly)
+    implies horizontal origin at 0,0.  Ie, the nil callback returns
+    true instead of false.  As such, implementations that have a
+    glyph_h_origin() that simply returns true, can remove that function
+    with HarfBuzz >= 1.1.2.  This results in a tiny speedup.
+
+
+Overview of changes leading to 1.1.1
+Wednesday, November 24, 2015
+====================================
+
+- Build fixes, specially for hb-coretext.
+
+
+Overview of changes leading to 1.1.0
+Wednesday, November 18, 2015
+====================================
+
+- Implement 'stch' stretch feature for Syriac Abbreviation Mark.
+  https://github.com/behdad/harfbuzz/issues/141
+- Disable use of decompose_compatibility() callback.
+- Implement "shaping" of various Unicode space characters, even
+  if the font does not support them.
+  https://github.com/behdad/harfbuzz/issues/153
+- If font does not support U+2011 NO-BREAK HYPHEN, fallback to
+  U+2010 HYPHEN.
+- Changes resulting from libFuzzer continuous fuzzing:
+  * Reject font tables that need more than 8 edits,
+  * Bound buffer growth during shaping to 32x,
+  * Fix assertions and other issues at OOM / buffer max-growth.
+- Misc fixes and optimizations.
+- API changes:
+  * All fonts created with hb_font_create() now inherit from
+    (ie. have parent) hb_font_get_empty().
+
+
+Overview of changes leading to 1.0.6
+Thursday, October 15, 2015
+====================================
+
+- Reduce max nesting level in OT lookups from 8 to 6.
+  Should not affect any real font as far as I know.
+- Fix memory access issue in ot-font.
+- Revert default load-flags of fonts created using hb_ft_font_create()
+  back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING.  This was changed in
+  last release (1.0.5), but caused major issues, so revert.
+  https://github.com/behdad/harfbuzz/issues/143
+
+
+Overview of changes leading to 1.0.5
+Tuesday, October 13, 2015
+====================================
+
+- Fix multiple memory access bugs discovered using libFuzzer.
+  https://github.com/behdad/harfbuzz/issues/139
+  Everyone should upgrade to this version as soon as possible.
+  We now have continuous fuzzing set up, to avoid issues like
+  these creeping in again.
+- Misc fixes.
+
+- New API:
+  * hb_font_set_parent().
+  * hb_ft_font_[sg]et_load_flags()
+    The default flags for fonts created using hb_ft_font_create()
+    has changed to default to FT_LOAD_DEFAULT now.  Previously it
+    was defaulting to FT_LOAD_DFEAULT|FT_LOAD_NO_HINTING.
+
+- API changes:
+  * Fonts now default to units-per-EM as their scale, instead of 0.
+  * hb_font_create_sub_font() does NOT make parent font immutable
+    anymore.  hb_font_make_immutable() does.
+
+
+Overview of changes leading to 1.0.4
+Wednesday, September 30, 2015
+====================================
+
+- Fix minor out-of-bounds read error.
+
+
+Overview of changes leading to 1.0.3
+Tuesday, September 1, 2015
+====================================
+
+- Start of user documentation, from Simon Cozens!
+- Implement glyph_extents() for TrueType fonts in hb-ot-font.
+- Improve GPOS cursive attachments with conflicting lookups.
+- More fixes for cluster-level = 1.
+- Uniscribe positioning fix.
+
+
+Overview of changes leading to 1.0.2
+Wednesday, August 19, 2015
+====================================
+
+- Fix shaping with cluster-level > 0.
+- Fix Uniscribe backend font-size scaling.
+- Declare dependencies in harfbuzz.pc.
+  FreeType is not declared though, to avoid bugs in pkg-config
+  0.26 with recursive dependencies.
+- Slightly improved debug infrastructure.  More to come later.
+- Misc build fixes.
+
+
+Overview of changes leading to 1.0.1
+Monday, July 27, 2015
+====================================
+
+- Fix out-of-bounds access in USE shaper.
+
+
+Overview of changes leading to 1.0.0
+Sunday, July 26, 2015
+====================================
+
+- Implement Universal Shaping Engine:
+  https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
+  http://blogs.windows.com/bloggingwindows/2015/02/23/windows-shapes-the-worlds-languages/
+- Bump version to 1.0.0.  The soname was NOT bumped.
+
+
+Overview of changes leading to 0.9.42
+Thursday, July 26, 2015
+=====================================
+
+- New API to allow for retrieving finer-grained cluster
+  mappings if the client desires to handle them.  Default
+  behavior is unchanged.
+- Fix cluster merging when removing default-ignorables.
+- Update to Unicode 8.0
+- hb-graphite2 fixes.
+- Misc fixes.
+- Removed HB_NO_MERGE_CLUSTERS hack.
+- New API:
+  hb_buffer_cluster_level_t enum
+  hb_buffer_get_cluster_level()
+  hb_buffer_set_cluster_level()
+  hb-shape / hb-view --cluster-level
+
+
+Overview of changes leading to 0.9.41
+Thursday, June 18, 2015
+=====================================
+
+- Fix hb-coretext with trailing whitespace in right-to-left.
+- New API: hb_buffer_reverse_range().
+- Allow implementing atomic ops in config.h.
+- Fix hb_language_t in language bindings.
+- Misc fixes.
+
+
+Overview of changes leading to 0.9.40
+Friday, March 20, 2015
+=====================================
+
+- Another hb-coretext crasher fix.  Ouch!
+- Happy Norouz!
+
+
+Overview of changes leading to 0.9.39
+Wednesday, March 4, 2015
+=====================================
+
+- Critical hb-coretext fixes.
+- Optimizations and refactoring; no functional change
+  expected.
+- Misc build fixes.
+
+
+Overview of changes leading to 0.9.38
+Friday, January 23, 2015
+=====================================
+
+- Fix minor out-of-bounds access in Indic shaper.
+- Change New Tai Lue shaping engine from South-East Asian to default,
+  reflecting change in Unicode encoding model.
+- Add hb-shape --font-size.  Can take up to two numbers for separate
+  x / y size.
+- Fix CoreText and FreeType scale issues with negative scales.
+- Reject blobs larger than 2GB.  This might break some icu-le-hb clients
+  that need security fixes.  See:
+  http://www.icu-project.org/trac/ticket/11450
+- Avoid accessing font tables during face destruction, in casce rogue
+  clients released face data already.
+- Fix up gobject-introspection a bit.  Python bindings kinda working.
+  See README.python.
+- Misc fixes.
+- API additions:
+  hb_ft_face_create_referenced()
+  hb_ft_font_create_referenced()
+
+
+Overview of changes leading to 0.9.37
+Wednesday, December 17, 2014
+=====================================
+
+- Fix out-of-bounds access in Context lookup format 3.
+- Indic: Allow ZWJ/ZWNJ before syllable modifiers.
+
+
+Overview of changes leading to 0.9.36
+Thursday, November 20, 2014
+=====================================
+
+- First time that three months went by without a release since
+  0.9.2 was released on August 10, 2012!
+- Fix performance bug in hb_ot_collect_glyphs():
+  https://bugzilla.mozilla.org/show_bug.cgi?id=1090869
+- Add basic vertical-text support to hb-ot-font.
+- Misc build fixes.
+
+
+Overview of changes leading to 0.9.35
+Saturday, August 13, 2014
+=====================================
+
+- Fix major shape-plan caching bug when more than one shaper were
+  provided to hb_shape_full() (as exercised by XeTeX).
+  http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1246370.html
+- Fix Arabic fallback shaping regression.  This was broken in 0.9.32.
+- Major hb-coretext fixes.  That backend is complete now, including
+  respecing buffer direction and language, down to vertical writing.
+- Build fixes for Windows CE.  Should build fine now.
+- Misc fixes:
+  Use atexit() only if it's safe to call from shared library
+  https://bugs.freedesktop.org/show_bug.cgi?id=82246
+  Mandaic had errors in its Unicode Joining_Type
+  https://bugs.freedesktop.org/show_bug.cgi?id=82306
+- API changes:
+
+  * hb_buffer_clear_contents() does not reset buffer flags now.
+
+    After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't
+    need to set flags for different pieces of text.  The flags now
+    are something the client sets up once, depending on how it
+    actually uses the buffer.  As such, don't clear it in
+    clear_contents().
+
+    I don't expect any changes to be needed to any existing client.
+
+
+Overview of changes leading to 0.9.34
+Saturday, August 2, 2014
+=====================================
+
+- hb_feature_from_string() now accepts CSS font-feature-settings format.
+- As a result, hb-shape / hb-view --features also accept CSS-style strings.
+  Eg, "'liga' off" is accepted now.
+- Add old-spec Myanmar shaper:
+  https://bugs.freedesktop.org/show_bug.cgi?id=81775
+- Don't apply 'calt' in Hangul shaper.
+- Fix mark advance zeroing for Hebrew shaper:
+  https://bugs.freedesktop.org/show_bug.cgi?id=76767
+- Implement Windows-1256 custom Arabic shaping.  Only built on Windows,
+  and requires help from get_glyph().  Used by Firefox.
+  https://bugzilla.mozilla.org/show_bug.cgi?id=1045139
+- Disable 'liga' in vertical text.
+- Build fixes.
+- API changes:
+
+  * Make HB_BUFFER_FLAG_BOT/EOT easier to use.
+
+    Previously, we expected users to provide BOT/EOT flags when the
+    text *segment* was at paragraph boundaries.  This meant that for
+    clients that provide full paragraph to HarfBuzz (eg. Pango), they
+    had code like this:
+
+      hb_buffer_set_flags (hb_buffer,
+                           (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) |
+                           (item_offset + item_length == paragraph_length ?
+                            HB_BUFFER_FLAG_EOT : 0));
+
+      hb_buffer_add_utf8 (hb_buffer,
+                          paragraph_text, paragraph_length,
+                          item_offset, item_length);
+
+    After this change such clients can simply say:
+
+      hb_buffer_set_flags (hb_buffer,
+                           HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
+
+      hb_buffer_add_utf8 (hb_buffer,
+                          paragraph_text, paragraph_length,
+                          item_offset, item_length);
+
+    Ie, HarfBuzz itself checks whether the segment is at the beginning/end
+    of the paragraph.  Clients that only pass item-at-a-time to HarfBuzz
+    continue not setting any flags whatsoever.
+
+    Another way to put it is: if there's pre-context text in the buffer,
+    HarfBuzz ignores the BOT flag.  If there's post-context, it ignores
+    EOT flag.
+
+
+Overview of changes leading to 0.9.33
+Tuesday, July 22, 2014
+=====================================
+
+- Turn off ARabic 'cswh' feature that was accidentally turned on.
+- Add HB_TAG_MAX_SIGNED.
+- Make hb_face_make_immutable() really make face immutable!
+- Windows build fixes.
+
+
+Overview of changes leading to 0.9.32
+Thursday, July 17, 2014
+=====================================
+
+- Apply Arabic shaping features in spec order exactly.
+- Another fix for Mongolian free variation selectors.
+- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt'
+  together.
+- Minor adjustment to U+FFFD logic.
+- Fix hb-coretext build.
+
+
+Overview of changes leading to 0.9.31
+Wednesday, July 16, 2014
+=====================================
+
+- Only accept valid UTF-8/16/32; we missed many cases before.
+- Better shaping of invalid UTF-8/16/32.  Falls back to
+  U+FFFD REPLACEMENT CHARACTER now.
+- With all changes in this release, the buffer will contain fully
+  valid Unicode after hb_buffer_add_utf8/16/32 no matter how
+  broken the input is.  This can be overriden though.  See below.
+- Fix Mongolian Variation Selectors for fonts without GDEF.
+- Fix minor invalid buffer access.
+- Accept zh-Hant and zh-Hans language tags.  hb_ot_tag_to_language()
+  now uses these instead of private tags.
+- Build fixes.
+- New API:
+  * hb_buffer_add_codepoints().  This does what hb_buffer_add_utf32()
+    used to do, ie. no validity check on the input at all.  add_utf32
+    now replaces invalid Unicode codepoints with the replacement
+    character (see below).
+  * hb_buffer_set_replacement_codepoint()
+  * hb_buffer_get_replacement_codepoint()
+    Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when
+    we detected broken input, we replaced that with (hb_codepoint_t)-1.
+    This has changed to use U+FFFD now, but can be changed using these
+    new API.
+
+
+Overview of changes leading to 0.9.30
+Wednesday, July 9, 2014
+=====================================
+
+- Update to Unicode 7.0.0:
+  * New scripts Manichaean and Psalter Pahlavi are shaped using
+    Arabic shaper.
+  * All the other new scripts to through the generic shaper for
+    now.
+- Minor Indic improvements.
+- Fix graphite2 backend cluster mapping [crasher!]
+- API changes:
+  * New HB_SCRIPT_* values for Unicode 7.0 scripts.
+  * New function hb_ot_layout_language_get_required_feature().
+- Build fixes.
+
+
+Overview of changes leading to 0.9.29
+Thursday, May 29, 2014
+=====================================
+
+- Implement cmap in hb-ot-font.h.  No variation-selectors yet.
+- Myanmar: Allow MedialYa+Asat.
+- Various Indic fixes:
+  * Support most characters in Extended Devanagary and Vedic
+    Unicode blocks.
+  * Allow digits and a some punctuation as consonant placeholders.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.28
+Monday, April 28, 2014
+=====================================
+
+- Unbreak old-spec Indic shaping. (bug 76705)
+- Fix shaping of U+17DD and U+0FC6.
+- Add HB_NO_MERGE_CLUSTERS build option.  NOT to be enabled by default
+  for shipping libraries.  It's an option for further experimentation
+  right now.  When we are sure how to do it properly, we will add
+  public run-time API for the functionality.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.27
+Tuesday, March 18, 2014
+=====================================
+
+- Don't use "register" storage class specifier
+- Wrap definition of free_langs() with HAVE_ATEXIT
+- Add coretext_aat shaper and hb_coretext_face_create() constructor
+- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks
+- Add Myanmar test case from OpenType Myanmar spec
+- Only do fallback Hebrew composition if no GPOS 'mark' available
+- Allow bootstrapping without gtk-doc
+- Use AM_MISSING_PROG for ragel and git
+- Typo in ucdn's Makefile.am
+- Improve MemoryBarrier() implementation
+
+
+Overview of changes leading to 0.9.26
+Thursday, January 30, 2014
+=====================================
+
+- Misc fixes.
+- Fix application of 'rtlm' feature.
+- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH.
+- New header: hb-ot-shape.h
+- Uniscribe: fix scratch-buffer accounting.
+- Reorder Tai Tham SAKOT to after tone-marks.
+- Add Hangul shaper.
+- New files:
+  hb-ot-shape-complex-hangul.cc
+  hb-ot-shape-complex-hebrew.cc
+  hb-ot-shape-complex-tibetan.cc
+- Disable 'cswh' feature in Arabic shaper.
+- Coretext: better handle surrogate pairs.
+- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE.
+
+
+Overview of changes leading to 0.9.25
+Wednesday, December 4, 2013
+=====================================
+
+- Myanmar shaper improvements.
+- Avoid font fallback in CoreText backend.
+- Additional OpenType language tag mappiongs.
+- More aggressive shape-plan caching.
+- Build with / require automake 1.13.
+- Build with libtool 2.4.2.418 alpha to support ppc64le.
+
+
+Overview of changes leading to 0.9.24
+Tuesday, November 13, 2013
+=====================================
+
+- Misc compiler warning fixes with clang.
+- No functional changes.
+
+
+Overview of changes leading to 0.9.23
+Monday, October 28, 2013
+=====================================
+
+- "Udupi HarfBuzz Hackfest", Paris, October 14..18 2013.
+- Fix (Chain)Context recursion with non-monotone lookup positions.
+- Misc Indic bug fixes.
+- New Javanese / Buginese shaping, similar to Windows 8.1.
+
+
+Overview of changes leading to 0.9.22
+Thursday, October 3, 2013
+=====================================
+
+- Fix use-after-end-of-scope in hb_language_from_string().
+- Fix hiding of default_ignorables if font doesn't have space glyph.
+- Protect against out-of-range lookup indices.
+
+- API Changes:
+
+  * Added hb_ot_layout_table_get_lookup_count()
+
+
+Overview of changes leading to 0.9.21
+Monday, September 16, 2013
+=====================================
+
+- Rename gobject-introspection library name from harfbuzz to HarfBuzz.
+- Remove (long disabled) hb-old and hb-icu-le test shapers.
+- Misc gtk-doc and gobject-introspection annotations.
+- Misc fixes.
+- API changes:
+
+  * Add HB_SET_VALUE_INVALID
+
+Overview of changes leading to 0.9.20
+Thursday, August 29, 2013
+=====================================
+
+General:
+- Misc substitute_closure() fixes.
+- Build fixes.
+
+Documentation:
+- gtk-doc boilerplate integrated.  Docs are built now, but
+  contain no contents.  By next release hopefully we have
+  some content in.  Enable using --enable-gtk-doc.
+
+GObject and Introspection:
+- Added harfbuzz-gobject library (hb-gobject.h) that has type
+  bindings for all HarfBuzz objects and enums.  Enable using
+  --with-gobject.
+- Added gobject-introspection boilerplate.  Nothing useful
+  right now.  Work in progress.  Gets enabled automatically if
+  --with-gobject is used.  Override with --disable-introspection.
+
+OpenType shaper:
+- Apply 'mark' in Myanmar shaper.
+- Don't apply 'dlig' by default.
+
+Uniscribe shaper:
+- Support user features.
+- Fix loading of fonts that are also installed on the system.
+- Fix shaping of Arabic Presentation Forms.
+- Fix build with wide chars.
+
+CoreText shaper:
+- Support user features.
+
+Source changes:
+- hb_face_t code moved to hb-face.h / hb-face.cc.
+- Added hb-deprecated.h.
+
+API changes:
+- Added HB_DISABLE_DEPRECATED.
+- Deprecated HB_SCRIPT_CANADIAN_ABORIGINAL; replaced by
+  HB_SCRIPT_CANADIAN_SYLLABICS.
+- Deprecated HB_BUFFER_FLAGS_DEFAULT; replaced by
+  HB_BUFFER_FLAG_DEFAULT.
+- Deprecated HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; replaced by
+  HB_BUFFER_SERIALIZE_FLAG_DEFAULT.
+
+
+Overview of changes leading to 0.9.19
+Tuesday, July 16, 2013
+=====================================
+
+- Build fixes.
+- Better handling of multiple variation selectors in a row.
+- Pass on variation selector to GSUB if not consumed by cmap.
+- Fix undefined memory access.
+- Add Javanese config to Indic shaper.
+- Misc bug fixes.
+
+Overview of changes leading to 0.9.18
+Tuesday, May 28, 2013
+=====================================
+
+New build system:
+
+- All unneeded code is all disabled by default,
+
+- Uniscribe and CoreText shapers can be enabled with their --with options,
+
+- icu_le and old shapers cannot be enabled for now,
+
+- glib, freetype, and cairo will be detected automatically.
+  They can be force on/off'ed with their --with options,
+
+- icu and graphite2 are default off, can be enabled with their --with
+  options,
+
+Moreover, ICU support is now build into a separate library:
+libharfbuzz-icu.so, and a new harfbuzz-icu.pc is shipped for it.
+Distros can enable ICU now without every application on earth
+getting linked to via libharfbuzz.so.
+
+For distros I recommend that they make sure they are building --with-glib
+--with-freetype --with-cairo, --with-icu, and optionally --with-graphite2;
+And package harfbuzz and harfbuzz-icu separately.
+
+
+Overview of changes leading to 0.9.17
+Monday, May 20, 2013
+=====================================
+
+- Build fixes.
+- Fix bug in hb_set_get_min().
+- Fix regression with Arabic mark positioning / width-zeroing.
+
+Overview of changes leading to 0.9.16
+Friday, April 19, 2013
+=====================================
+
+- Major speedup in OpenType lookup processing.  With the Amiri
+  Arabic font, this release is over 3x faster than previous
+  release.  All scripts / languages should see this speedup.
+
+- New --num-iterations option for hb-shape / hb-view; useful for
+  profiling.
+
+Overview of changes leading to 0.9.15
+Friday, April 05, 2013
+=====================================
+
+- Build fixes.
+- Fix crasher in graphite2 shaper.
+- Fix Arabic mark width zeroing regression.
+- Don't compose Hangul jamo into Unicode syllables.
+
+
+Overview of changes leading to 0.9.14
+Thursday, March 21, 2013
+=====================================
+
+- Build fixes.
+- Fix time-consuming sanitize with malicious fonts.
+- Implement hb_buffer_deserialize_glyphs() for both json and text.
+- Do not ignore Hangul filler characters.
+- Indic fixes:
+  * Fix Malayalam pre-base reordering interaction with post-forms.
+  * Further adjust ZWJ handling.  Should fix known regressions from
+    0.9.13.
+
+
+Overview of changes leading to 0.9.13
+Thursday, February 25, 2013
+=====================================
+
+- Build fixes.
+- Ngapi HarfBuzz Hackfest in London (February 2013):
+  * Fixed all known Indic bugs,
+  * New Win8-style Myanmar shaper,
+  * New South-East Asian shaper for Tai Tham, Cham, and New Tai Lue,
+  * Smartly ignore Default_Ignorable characters (joiners, etc) wheb
+    matching GSUB/GPOS lookups,
+  * Fix 'Phags-Pa U+A872 shaping,
+  * Fix partial disabling of default-on features,
+  * Allow disabling of TrueType kerning.
+- Fix possible crasher with broken fonts with overlapping tables.
+- Removed generated files from git again.  So, one needs ragel to
+  bootstrap from the git tree.
+
+API changes:
+- hb_shape() and related APIs now abort if buffer direction is
+  HB_DIRECTION_INVALID.  Previously, hb_shape() was calling
+  hb_buffer_guess_segment_properties() on the buffer before
+  shaping.  The heuristics in that function are fragile.  If the
+  user really wants the old behvaior, they can call that function
+  right before calling hb_shape() to get the old behavior.
+- hb_blob_create_sub_blob() always creates sub-blob with
+  HB_MEMORY_MODE_READONLY.  See comments for the reason.
+
+
+Overview of changes leading to 0.9.12
+Thursday, January 18, 2013
+=====================================
+
+- Build fixes for Sun compiler.
+- Minor bug fix.
+
+Overview of changes leading to 0.9.11
+Thursday, January 10, 2013
+=====================================
+
+- Build fixes.
+- Fix GPOS mark attachment with null Anchor offsets.
+- [Indic] Fix old-spec reordering of viramas if sequence ends in one.
+- Fix multi-threaded shaper data creation crash.
+- Add atomic ops for Solaris.
+
+API changes:
+- Rename hb_buffer_clear() to hb_buffer_clear_contents().
+
+
+Overview of changes leading to 0.9.10
+Thursday, January 3, 2013
+=====================================
+
+- [Indic] Fixed rendering of Malayalam dot-reph
+- Updated OT language tags.
+- Updated graphite2 backend.
+- Improved hb_ot_layout_get_size_params() logic.
+- Improve hb-shape/hb-view help output.
+- Fixed hb-set.h implementation to not crash.
+- Fixed various issues with hb_ot_layout_collect_lookups().
+- Various build fixes.
+
+New API:
+
+hb_graphite2_face_get_gr_face()
+hb_graphite2_font_get_gr_font()
+hb_coretext_face_get_cg_font()
+
+Modified API:
+
+hb_ot_layout_get_size_params()
+
+
+Overview of changes leading to 0.9.9
+Wednesday, December 5, 2012
+====================================
+
+- Fix build on Windows.
+- Minor improvements.
+
+
+Overview of changes leading to 0.9.8
+Tuesday, December 4, 2012
+====================================
+
+
+- Actually implement hb_shape_plan_get_shaper ().
+- Make UCDB data tables const.
+- Lots of internal refactoring in OTLayout tables.
+- Flesh out hb_ot_layout_lookup_collect_glyphs().
+
+New API:
+
+hb_ot_layout_collect_lookups()
+hb_ot_layout_get_size_params()
+
+
+Overview of changes leading to 0.9.7
+Sunday, November 21, 2012
+====================================
+
+
+HarfBuzz "All-You-Can-Eat-Sushi" (aka Vancouver) Hackfest and follow-on fixes.
+
+- Fix Arabic contextual joining using pre-context text.
+- Fix Sinhala "split matra" mess.
+- Fix Khmer shaping with broken fonts.
+- Implement Thai "PUA" shaping for old fonts.
+- Do NOT route Kharoshthi script through the Indic shaper.
+- Disable fallback positioning for Indic and Thai shapers.
+- Misc fixes.
+
+
+hb-shape / hb-view changes:
+
+- Add --text-before and --text-after
+- Add --bot / --eot / --preserve-default-ignorables
+- hb-shape --output-format=json
+
+
+New API:
+
+hb_buffer_clear()
+
+hb_buffer_flags_t
+
+HB_BUFFER_FLAGS_DEFAULT
+HB_BUFFER_FLAG_BOT
+HB_BUFFER_FLAG_EOT
+HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
+
+hb_buffer_set_flags()
+hb_buffer_get_flags()
+
+HB_BUFFER_SERIALIZE_FLAGS
+hb_buffer_serialize_glyphs()
+hb_buffer_deserialize_glyphs()
+hb_buffer_serialize_list_formats()
+
+hb_set_add_range()
+hb_set_del_range()
+hb_set_get_population()
+hb_set_next_range()
+
+hb_face_[sg]et_glyph_count()
+
+hb_segment_properties_t
+HB_SEGMENT_PROPERTIES_DEFAULT
+hb_segment_properties_equal()
+hb_segment_properties_hash()
+
+hb_buffer_set_segment_properties()
+hb_buffer_get_segment_properties()
+
+hb_ot_layout_glyph_class_t
+hb_ot_layout_get_glyph_class()
+hb_ot_layout_get_glyphs_in_class()
+
+hb_shape_plan_t
+hb_shape_plan_create()
+hb_shape_plan_create_cached()
+hb_shape_plan_get_empty()
+hb_shape_plan_reference()
+hb_shape_plan_destroy()
+hb_shape_plan_set_user_data()
+hb_shape_plan_get_user_data()
+hb_shape_plan_execute()
+hb_shape_plan_get_shaper()
+
+hb_ot_shape_plan_collect_lookups()
+
+
+API changes:
+
+- Remove "mask" parameter from hb_buffer_add().
+- Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup().
+- hb-set.h API const correction.
+- Renamed hb_set_min/max() to hb_set_get_min/max().
+- Rename hb_ot_layout_feature_get_lookup_indexes() to hb_ot_layout_feature_get_lookups().
+- Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties().
+
+
+
+Overview of changes leading to 0.9.6
+Sunday, November 13, 2012
+====================================
+
+- Don't clear pre-context text if no new context is provided.
+- Fix ReverseChainingSubstLookup, which was totally borked.
+- Adjust output format of hb-shape a bit.
+- Include config.h.in in-tree.  Makes it easier for alternate build systems.
+- Fix hb_buffer_set_length(buffer, 0) invalid memory allocation.
+- Use ICU LayoutEngine's C API instead of C++.  Avoids much headache.
+- Drop glyphs for all of Unicode Default_Ignorable characters.
+- Misc build fixes.
+
+Arabic shaper:
+- Enable 'dlig' and 'mset' features in Arabic shaper.
+- Implement 'Phags-pa shaping, improve Mongolian.
+
+Indic shaper:
+- Decompose Sinhala split matras the way old HarfBuzz / Pango did.
+- Initial support for Consonant Medials.
+- Start adding new-style Myanmar shaping.
+- Make reph and 'pref' logic introspect the font.
+- Route Meetei-Mayek through the Indic shaper.
+- Don't apply 'liga' in Indic shaper.
+- Improve Malayalam pre-base reordering Ra interaction with Chillus.
+
+
+
+Overview of changes leading to 0.9.5
+Sunday, October 14, 2012
+====================================
+
+- Synthetic-GSUB Arabic fallback shaping.
+
+- Misc Indic improvements.
+
+- Add build system support for pthread.
+
+- Imported UCDN for in-tree Unicode callbacks implementation.
+
+- Context-aware Arabic joining.
+
+- Misc other fixes.
+
+- New API:
+
+  hb_feature_to/from-string()
+  hb_buffer_[sg]et_content_type()
+
+
+
+Overview of changes leading to 0.9.4
+Tuesday, Sep 03, 2012
+====================================
+
+- Indic improvements with old-spec Malayalam.
+
+- Better fallback glyph positioning, specially with Thai / Lao marks.
+
+- Implement dotted-circle insertion.
+
+- Better Arabic fallback shaping / ligation.
+
+- Added ICU LayoutEngine backend for testing.  Call it by the 'icu_le' name.
+
+- Misc fixes.
+
+
+
+Overview of changes leading to 0.9.3
+Friday, Aug 18, 2012
+====================================
+
+- Fixed fallback mark positioning for left-to-right text.
+
+- Improve mark positioning for the remaining combining classes.
+
+- Unbreak Thai and fallback Arabic shaping.
+
+- Port Arabic shaper to shape-plan caching.
+
+- Use new ICU normalizer functions.
+
+
+
+Overview of changes leading to 0.9.2
+Friday, Aug 10, 2012
+====================================
+
+- Over a thousand commits!  This is the first major release of HarfBuzz.
+
+- HarfBuzz is feature-complete now!  It should be in par, or better, than
+  both Pango's shapers and old HarfBuzz / Qt shapers.
+
+- New Indic shaper, supporting main Indic scripts, Sinhala, and Khmer.
+
+- Improved Arabic shaper, with fallback Arabic shaping, supporting Arabic,
+  Sinhala, N'ko, Mongolian, and Mandaic.
+
+- New Thai / Lao shaper.
+
+- Tibetan / Hangul support in the generic shaper.
+
+- Synthetic GDEF support for fonts without a GDEF table.
+
+- Fallback mark positioning for fonts without a GPOS table.
+
+- Unicode normalization shaping heuristic during glyph mapping.
+
+- New experimental Graphite2 backend.
+
+- New Uniscribe backend (primarily for testing).
+
+- New CoreText backend (primarily for testing).
+
+- Major optimization and speedup.
+
+- Test suites and testing infrastructure (work in progress).
+
+- Greatly improved hb-view cmdline tool.
+
+- hb-shape cmdline tool.
+
+- Unicode 6.1 support.
+
+Summary of API changes:
+
+o Changed API:
+
+  - Users are expected to only include main header files now (ie. hb.h,
+    hb-glib.h, hb-ft.h, ...)
+
+  - All struct tag names had their initial underscore removed.
+    Ie. "struct _hb_buffer_t" is "struct hb_buffer_t" now.
+
+  - All set_user_data() functions now take a "replace" boolean parameter.
+
+  - hb_buffer_create() takes zero arguments now.
+    Use hb_buffer_pre_allocate() to pre-allocate.
+
+  - hb_buffer_add_utf*() now accept -1 for length parameteres,
+    meaning "nul-terminated".
+
+  - hb_direction_t enum values changed.
+
+  - All *_from_string() APIs now take a length parameter to allow for
+    non-nul-terminated strings. A -1 length means "nul-terminated".
+
+  - Typedef for hb_language_t changed.
+
+  - hb_get_table_func_t renamed to hb_reference_table_func_t.
+
+  - hb_ot_layout_table_choose_script()
+
+  - Various renames in hb-unicode.h.
+
+o New API:
+
+  - hb_buffer_guess_properties()
+    Automatically called by hb_shape().
+
+  - hb_buffer_normalize_glyphs()
+
+  - hb_tag_from_string()
+
+  - hb-coretext.h
+
+  - hb-uniscribe.h
+
+  - hb_face_reference_blob()
+  - hb_face_[sg]et_index()
+  - hb_face_set_upem()
+
+  - hb_font_get_glyph_name_func_t
+    hb_font_get_glyph_from_name_func_t
+    hb_font_funcs_set_glyph_name_func()
+    hb_font_funcs_set_glyph_from_name_func()
+    hb_font_get_glyph_name()
+    hb_font_get_glyph_from_name()
+    hb_font_glyph_to_string()
+    hb_font_glyph_from_string()
+
+  - hb_font_set_funcs_data()
+
+  - hb_ft_font_set_funcs()
+  - hb_ft_font_get_face()
+
+  - hb-gobject.h (work in progress)
+
+  - hb_ot_shape_glyphs_closure()
+    hb_ot_layout_substitute_closure_lookup()
+
+  - hb-set.h
+
+  - hb_shape_full()
+
+  - hb_unicode_combining_class_t
+
+  - hb_unicode_compose_func_t
+    hb_unicode_decompose_func_t
+    hb_unicode_decompose_compatibility_func_t
+    hb_unicode_funcs_set_compose_func()
+    hb_unicode_funcs_set_decompose_func()
+    hb_unicode_funcs_set_decompose_compatibility_func()
+    hb_unicode_compose()
+    hb_unicode_decompose()
+    hb_unicode_decompose_compatibility()
+
+o Removed API:
+
+  - hb_ft_get_font_funcs()
+
+  - hb_ot_layout_substitute_start()
+    hb_ot_layout_substitute_lookup()
+    hb_ot_layout_substitute_finish()
+    hb_ot_layout_position_start()
+    hb_ot_layout_position_lookup()
+    hb_ot_layout_position_finish()
+
+
+
+Overview of changes leading to 0.6.0
+Friday, May 27, 2011
+====================================
+
+- Vertical text support in GPOS
+- Almost all API entries have unit tests now, under test/
+- All thread-safety issues are fixed
+
+Summary of API changes follows.
+
+
+* Simple Types API:
+
+  o New API:
+    HB_LANGUAGE_INVALID
+    hb_language_get_default()
+    hb_direction_to_string()
+    hb_direction_from_string()
+    hb_script_get_horizontal_direction()
+    HB_UNTAG()
+
+  o Renamed API:
+    hb_category_t renamed to hb_unicode_general_category_t
+
+  o Changed API:
+    hb_language_t is a typed pointers now
+
+  o Removed API:
+    HB_TAG_STR()
+
+
+* Use ISO 15924 tags for hb_script_t:
+
+  o New API:
+    hb_script_from_iso15924_tag()
+    hb_script_to_iso15924_tag()
+    hb_script_from_string()
+
+  o Changed API:
+    HB_SCRIPT_* enum members changed value.
+
+
+* Buffer API streamlined:
+
+  o New API:
+    hb_buffer_reset()
+    hb_buffer_set_length()
+    hb_buffer_allocation_successful()
+
+  o Renamed API:
+    hb_buffer_ensure() renamed to hb_buffer_pre_allocate()
+    hb_buffer_add_glyph() renamed to hb_buffer_add()
+
+  o Removed API:
+    hb_buffer_clear()
+    hb_buffer_clear_positions()
+
+  o Changed API:
+    hb_buffer_get_glyph_infos() takes an out length parameter now
+    hb_buffer_get_glyph_positions() takes an out length parameter now
+
+
+* Blob API streamlined:
+
+  o New API:
+    hb_blob_get_data()
+    hb_blob_get_data_writable()
+
+  o Renamed API:
+    hb_blob_create_empty() renamed to hb_blob_get_empty()
+
+  o Removed API:
+    hb_blob_lock()
+    hb_blob_unlock()
+    hb_blob_is_writable()
+    hb_blob_try_writable()
+
+  o Changed API:
+    hb_blob_create() takes user_data before destroy now
+
+
+* Unicode functions API:
+
+  o Unicode function vectors can subclass other unicode function vectors now.
+    Unimplemented callbacks in the subclass automatically chainup to the parent.
+
+  o All hb_unicode_funcs_t callbacks take a user_data now.  Their setters
+    take a user_data and its respective destroy callback.
+
+  o New API:
+    hb_unicode_funcs_get_empty()
+    hb_unicode_funcs_get_default()
+    hb_unicode_funcs_get_parent()
+
+  o Changed API:
+    hb_unicode_funcs_create() now takes a parent_funcs.
+
+  o Removed func getter functions:
+    hb_unicode_funcs_get_mirroring_func()
+    hb_unicode_funcs_get_general_category_func()
+    hb_unicode_funcs_get_script_func()
+    hb_unicode_funcs_get_combining_class_func()
+    hb_unicode_funcs_get_eastasian_width_func()
+
+
+* Face API:
+
+  o Renamed API:
+    hb_face_get_table() renamed to hb_face_reference_table()
+    hb_face_create_for_data() renamed to hb_face_create()
+
+  o Changed API:
+    hb_face_create_for_tables() takes user_data before destroy now
+    hb_face_reference_table() returns empty blob instead of NULL
+    hb_get_table_func_t accepts the face as first parameter now
+
+* Font API:
+
+  o Fonts can subclass other fonts now.  Unimplemented callbacks in the
+    subclass automatically chainup to the parent.  When chaining up,
+    scale is adjusted if the parent font has a different scale.
+
+  o All hb_font_funcs_t callbacks take a user_data now.  Their setters
+    take a user_data and its respective destroy callback.
+
+  o New API:
+    hb_font_get_parent()
+    hb_font_funcs_get_empty()
+    hb_font_create_sub_font()
+
+  o Removed API:
+    hb_font_funcs_copy()
+    hb_font_unset_funcs()
+
+  o Removed func getter functions:
+    hb_font_funcs_get_glyph_func()
+    hb_font_funcs_get_glyph_advance_func()
+    hb_font_funcs_get_glyph_extents_func()
+    hb_font_funcs_get_contour_point_func()
+    hb_font_funcs_get_kerning_func()
+
+  o Changed API:
+    hb_font_create() takes a face and references it now
+    hb_font_set_funcs() takes user_data before destroy now
+    hb_font_set_scale() accepts signed integers now
+    hb_font_get_contour_point_func_t now takes glyph first, then point_index
+    hb_font_get_glyph_func_t returns a success boolean now
+
+
+* Changed object model:
+
+  o All object types have a _get_empty() now:
+    hb_blob_get_empty()
+    hb_buffer_get_empty()
+    hb_face_get_empty()
+    hb_font_get_empty()
+    hb_font_funcs_get_empty()
+    hb_unicode_funcs_get_empty()
+
+  o Added _set_user_data() and _get_user_data() for all object types:
+    hb_blob_get_user_data()
+    hb_blob_set_user_data()
+    hb_buffer_get_user_data()
+    hb_buffer_set_user_data()
+    hb_face_get_user_data()
+    hb_face_set_user_data()
+    hb_font_funcs_get_user_data()
+    hb_font_funcs_set_user_data()
+    hb_font_get_user_data()
+    hb_font_set_user_data()
+    hb_unicode_funcs_get_user_data()
+    hb_unicode_funcs_set_user_data()
+
+  o Removed the _get_reference_count() from all object types:
+    hb_blob_get_reference_count()
+    hb_buffer_get_reference_count()
+    hb_face_get_reference_count()
+    hb_font_funcs_get_reference_count()
+    hb_font_get_reference_count()
+    hb_unicode_funcs_get_reference_count()
+
+  o Added _make_immutable() and _is_immutable() for all object types except for buffer:
+    hb_blob_make_immutable()
+    hb_blob_is_immutable()
+    hb_face_make_immutable()
+    hb_face_is_immutable()
+
+
+* Changed API for vertical text support
+
+  o The following callbacks where removed:
+    hb_font_get_glyph_advance_func_t
+    hb_font_get_kerning_func_t
+
+  o The following new callbacks added instead:
+    hb_font_get_glyph_h_advance_func_t
+    hb_font_get_glyph_v_advance_func_t
+    hb_font_get_glyph_h_origin_func_t
+    hb_font_get_glyph_v_origin_func_t
+    hb_font_get_glyph_h_kerning_func_t
+    hb_font_get_glyph_v_kerning_func_t
+
+  o The following API removed as such:
+    hb_font_funcs_set_glyph_advance_func()
+    hb_font_funcs_set_kerning_func()
+    hb_font_get_glyph_advance()
+    hb_font_get_kerning()
+
+  o New API added instead:
+    hb_font_funcs_set_glyph_h_advance_func()
+    hb_font_funcs_set_glyph_v_advance_func()
+    hb_font_funcs_set_glyph_h_origin_func()
+    hb_font_funcs_set_glyph_v_origin_func()
+    hb_font_funcs_set_glyph_h_kerning_func()
+    hb_font_funcs_set_glyph_v_kerning_func()
+    hb_font_get_glyph_h_advance()
+    hb_font_get_glyph_v_advance()
+    hb_font_get_glyph_h_origin()
+    hb_font_get_glyph_v_origin()
+    hb_font_get_glyph_h_kerning()
+    hb_font_get_glyph_v_kerning()
+
+  o The following higher-leve API added for convenience:
+    hb_font_get_glyph_advance_for_direction()
+    hb_font_get_glyph_origin_for_direction()
+    hb_font_add_glyph_origin_for_direction()
+    hb_font_subtract_glyph_origin_for_direction()
+    hb_font_get_glyph_kerning_for_direction()
+    hb_font_get_glyph_extents_for_origin()
+    hb_font_get_glyph_contour_point_for_origin()
+
+
+* OpenType Layout API:
+
+  o New API:
+    hb_ot_layout_position_start()
+    hb_ot_layout_substitute_start()
+    hb_ot_layout_substitute_finish()
+
+
+* Glue code:
+
+  o New API:
+    hb_glib_script_to_script()
+    hb_glib_script_from_script()
+    hb_icu_script_to_script()
+    hb_icu_script_from_script()
+
+
+* Version API added:
+
+  o New API:
+    HB_VERSION_MAJOR
+    HB_VERSION_MINOR
+    HB_VERSION_MICRO
+    HB_VERSION_STRING
+    HB_VERSION_CHECK()
+    hb_version()
+    hb_version_string()
+    hb_version_check()
+
+
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,14 +1,14 @@
-gfx/harfbuzz status as of 2017-01-25:
+gfx/harfbuzz status as of 2017-02-25:
 
 This directory contains the harfbuzz source from the 'master' branch of
 https://github.com/behdad/harfbuzz.
 
-Current version: 1.4.2
+Current version: 1.4.3
 
 UPDATING:
 
 Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
 repository. It is created at build time by the harfbuzz build system;
 but as we don't use that build system in mozilla, it is necessary to refresh
 this file when updating harfbuzz, and check it into the mozilla tree.
 
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,11 +1,11 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.4.2],
+        [1.4.3],
         [https://github.com/behdad/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -213,17 +213,17 @@ CLEANFILES += $(pkgconfig_DATA)
 
 
 CLEANFILES += harfbuzz.def
 harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
 	$(AM_V_GEN) (echo EXPORTS; \
 	(cat $^ || echo 'hb_ERROR ()' ) | \
 	$(EGREP) '^hb_.* \(' | \
 	sed -e 's/ (.*//' | \
-	LANG=C sort; \
+	LC_ALL=C sort; \
 	echo LIBRARY libharfbuzz-0.dll; \
 	) >"$@"
 	@ ! grep -q hb_ERROR "$@" \
 	|| ($(RM) "$@"; false)
 
 
 GENERATORS = \
 	gen-arabic-table.py \
--- a/gfx/harfbuzz/src/harfbuzz-icu.pc
+++ b/gfx/harfbuzz/src/harfbuzz-icu.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library ICU integration
-Version: 1.4.2
+Version: 1.4.3
 
 Requires: harfbuzz
 Requires.private: icu-uc
 Libs: -L${libdir} -lharfbuzz-icu
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc
+++ b/gfx/harfbuzz/src/harfbuzz.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
-Version: 1.4.2
+Version: 1.4.3
 
 Libs: -L${libdir} -lharfbuzz
 Libs.private:    
 Requires.private: glib-2.0 >= 2.19.1 
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -64,18 +64,18 @@ reference_table  (hb_face_t *face HB_UNU
 
 hb_face_t *
 hb_coretext_face_create (CGFontRef cg_font)
 {
   return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
 }
 
 
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
+HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font)
 
 
 /*
  * shaper face data
  */
 
 static CTFontDescriptorRef
 get_last_resort_font_desc (void)
@@ -1217,16 +1217,19 @@ fail:
   return ret;
 }
 
 
 /*
  * AAT shaper
  */
 
+HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
+
 /*
  * shaper face data
  */
 
 struct hb_coretext_aat_shaper_face_data_t {};
 
 hb_coretext_aat_shaper_face_data_t *
 _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
--- a/gfx/harfbuzz/src/hb-directwrite.cc
+++ b/gfx/harfbuzz/src/hb-directwrite.cc
@@ -29,18 +29,18 @@
 
 #include "hb-directwrite.h"
 
 
 #ifndef HB_DEBUG_DIRECTWRITE
 #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
 #endif
 
-HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font)
+HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font)
 
 
 /*
  * DirectWrite font stream helpers
  */
 
 // This is a font loader which provides only one font (unlike its original design).
 // For a better implementation which was also source of this
--- a/gfx/harfbuzz/src/hb-face-private.hh
+++ b/gfx/harfbuzz/src/hb-face-private.hh
@@ -49,16 +49,23 @@ struct hb_face_t {
   hb_reference_table_func_t  reference_table_func;
   void                      *user_data;
   hb_destroy_func_t          destroy;
 
   unsigned int index;			/* Face index in a collection, zero-based. */
   mutable unsigned int upem;		/* Units-per-EM. */
   mutable unsigned int num_glyphs;	/* Number of glyphs. */
 
+  enum dirty_t {
+    NOTHING	= 0x0000,
+    INDEX	= 0x0001,
+    UPEM	= 0x0002,
+    NUM_GLYPHS	= 0x0004,
+  } dirty;
+
   struct hb_shaper_data_t shaper_data;	/* Various shaper data. */
 
   /* Various non-shaping data. */
   /* ... */
 
   /* Cache */
   struct plan_node_t {
     hb_shape_plan_t *shape_plan;
@@ -94,16 +101,18 @@ struct hb_face_t {
     return num_glyphs;
   }
 
   private:
   HB_INTERNAL void load_upem (void) const;
   HB_INTERNAL void load_num_glyphs (void) const;
 };
 
+HB_MARK_AS_FLAG_T (hb_face_t::dirty_t);
+
 extern HB_INTERNAL const hb_face_t _hb_face_nil;
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -46,16 +46,18 @@ const hb_face_t _hb_face_nil = {
   NULL, /* reference_table_func */
   NULL, /* user_data */
   NULL, /* destroy */
 
   0,    /* index */
   1000, /* upem */
   0,    /* num_glyphs */
 
+  hb_face_t::NOTHING, /* dirty */
+
   {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   },
 
   NULL, /* shape_plans */
 };
@@ -166,17 +168,17 @@ hb_face_create (hb_blob_t    *blob,
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
 
   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
 				    closure,
 				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
 
-  hb_face_set_index (face, index);
+  face->index = index;
 
   return face;
 }
 
 /**
  * hb_face_get_empty:
  *
  * 
@@ -360,16 +362,21 @@ hb_face_reference_blob (hb_face_t *face)
  **/
 void
 hb_face_set_index (hb_face_t    *face,
 		   unsigned int  index)
 {
   if (face->immutable)
     return;
 
+  if (face->index == index)
+    return;
+
+  face->dirty |= face->INDEX;
+
   face->index = index;
 }
 
 /**
  * hb_face_get_index:
  * @face: a face.
  *
  * 
@@ -395,16 +402,21 @@ hb_face_get_index (hb_face_t    *face)
  **/
 void
 hb_face_set_upem (hb_face_t    *face,
 		  unsigned int  upem)
 {
   if (face->immutable)
     return;
 
+  if (face->upem == upem)
+    return;
+
+  face->dirty |= face->UPEM;
+
   face->upem = upem;
 }
 
 /**
  * hb_face_get_upem:
  * @face: a face.
  *
  * 
@@ -439,16 +451,21 @@ hb_face_t::load_upem (void) const
  **/
 void
 hb_face_set_glyph_count (hb_face_t    *face,
 			 unsigned int  glyph_count)
 {
   if (face->immutable)
     return;
 
+  if (face->num_glyphs == glyph_count)
+    return;
+
+  face->dirty |= face->NUM_GLYPHS;
+
   face->num_glyphs = glyph_count;
 }
 
 /**
  * hb_face_get_glyph_count:
  * @face: a face.
  *
  * 
--- a/gfx/harfbuzz/src/hb-fallback-shape.cc
+++ b/gfx/harfbuzz/src/hb-fallback-shape.cc
@@ -23,16 +23,20 @@
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #define HB_SHAPER fallback
 #include "hb-shaper-impl-private.hh"
 
 
+HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
+
+
 /*
  * shaper face data
  */
 
 struct hb_fallback_shaper_face_data_t {};
 
 hb_fallback_shaper_face_data_t *
 _hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
@@ -120,17 +124,17 @@ hb_bool_t
   for (unsigned int i = 0; i < count; i++)
   {
     if (has_space && unicode->is_default_ignorable (info[i].codepoint)) {
       info[i].codepoint = space;
       pos[i].x_advance = 0;
       pos[i].y_advance = 0;
       continue;
     }
-    font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
+    (void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
     font->get_glyph_advance_for_direction (info[i].codepoint,
 					   direction,
 					   &pos[i].x_advance,
 					   &pos[i].y_advance);
     font->subtract_glyph_origin_for_direction (info[i].codepoint,
 					       direction,
 					       &pos[i].x_offset,
 					       &pos[i].y_offset);
--- a/gfx/harfbuzz/src/hb-font-private.hh
+++ b/gfx/harfbuzz/src/hb-font-private.hh
@@ -111,16 +111,26 @@ struct hb_font_t {
   /* Font variation coordinates. */
   unsigned int num_coords;
   int *coords;
 
   hb_font_funcs_t   *klass;
   void              *user_data;
   hb_destroy_func_t  destroy;
 
+  enum dirty_t {
+    NOTHING	= 0x0000,
+    FACE	= 0x0001,
+    PARENT	= 0x0002,
+    FUNCS	= 0x0004,
+    SCALE	= 0x0008,
+    PPEM	= 0x0010,
+    VARIATIONS	= 0x0020,
+  } dirty;
+
   struct hb_shaper_data_t shaper_data;
 
 
   /* Convert from font-space to user-space */
   inline int dir_scale (hb_direction_t direction)
   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
@@ -538,16 +548,18 @@ struct hb_font_t {
     return (hb_position_t) (scaled / upem);
   }
   inline hb_position_t em_scalef (float v, int scale)
   {
     return (hb_position_t) (v * scale / face->get_upem ());
   }
 };
 
+HB_MARK_AS_FLAG_T (hb_font_t::dirty_t);
+
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 
 
 #endif /* HB_FONT_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -1191,16 +1191,18 @@ hb_font_get_empty (void)
 
     0, /* num_coords */
     NULL, /* coords */
 
     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
     NULL, /* user_data */
     NULL, /* destroy */
 
+    hb_font_t::NOTHING, /* dirty */
+
     {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
     }
   };
 
   return const_cast<hb_font_t *> (&_hb_font_nil);
@@ -1343,16 +1345,21 @@ hb_font_set_parent (hb_font_t *font,
 		    hb_font_t *parent)
 {
   if (font->immutable)
     return;
 
   if (!parent)
     parent = hb_font_get_empty ();
 
+  if (parent == font->parent)
+    return;
+
+  font->dirty |= font->PARENT;
+
   hb_font_t *old = font->parent;
 
   font->parent = hb_font_reference (parent);
 
   hb_font_destroy (old);
 }
 
 /**
@@ -1367,16 +1374,47 @@ hb_font_set_parent (hb_font_t *font,
  **/
 hb_font_t *
 hb_font_get_parent (hb_font_t *font)
 {
   return font->parent;
 }
 
 /**
+ * hb_font_set_face:
+ * @font: a font.
+ * @face: new face.
+ *
+ * Sets font-face of @font.
+ *
+ * Since: 1.4.3
+ **/
+void
+hb_font_set_face (hb_font_t *font,
+		  hb_face_t *face)
+{
+  if (font->immutable)
+    return;
+
+  if (unlikely (!face))
+    face = hb_face_get_empty ();
+
+  if (font->face == face)
+    return;
+
+  font->dirty |= font->FACE;
+
+  hb_face_t *old = font->face;
+
+  font->face = hb_face_reference (face);
+
+  hb_face_destroy (old);
+}
+
+/**
  * hb_font_get_face:
  * @font: a font.
  *
  * 
  *
  * Return value: (transfer none): 
  *
  * Since: 0.9.2
@@ -1412,16 +1450,18 @@ hb_font_set_funcs (hb_font_t         *fo
   }
 
   if (font->destroy)
     font->destroy (font->user_data);
 
   if (!klass)
     klass = hb_font_funcs_get_empty ();
 
+  font->dirty |= font->FUNCS;
+
   hb_font_funcs_reference (klass);
   hb_font_funcs_destroy (font->klass);
   font->klass = klass;
   font->user_data = font_data;
   font->destroy = destroy;
 }
 
 /**
@@ -1467,16 +1507,21 @@ hb_font_set_funcs_data (hb_font_t       
 void
 hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale)
 {
   if (font->immutable)
     return;
 
+  if (font->x_scale == x_scale && font->y_scale == y_scale)
+    return;
+
+  font->dirty |= font->SCALE;
+
   font->x_scale = x_scale;
   font->y_scale = y_scale;
 }
 
 /**
  * hb_font_get_scale:
  * @font: a font.
  * @x_scale: (out): 
@@ -1508,16 +1553,21 @@ hb_font_get_scale (hb_font_t *font,
 void
 hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem)
 {
   if (font->immutable)
     return;
 
+  if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
+    return;
+
+  font->dirty |= font->PPEM;
+
   font->x_ppem = x_ppem;
   font->y_ppem = y_ppem;
 }
 
 /**
  * hb_font_get_ppem:
  * @font: a font.
  * @x_ppem: (out): 
@@ -1540,16 +1590,26 @@ hb_font_get_ppem (hb_font_t *font,
  * Variations
  */
 
 static void
 _hb_font_adopt_var_coords_normalized (hb_font_t *font,
 				      int *coords, /* 2.14 normalized */
 				      unsigned int coords_length)
 {
+  if (font->num_coords == coords_length &&
+      (coords_length == 0 ||
+       0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0]))))
+  {
+    free (coords);
+    return;
+  }
+
+  font->dirty |= font->VARIATIONS;
+
   free (font->coords);
 
   font->coords = coords;
   font->num_coords = coords_length;
 }
 
 /**
  * hb_font_set_variations:
@@ -1622,17 +1682,17 @@ hb_font_set_var_coords_normalized (hb_fo
 
   if (coords_length)
     memcpy (copy, coords, coords_length * sizeof (coords[0]));
 
   _hb_font_adopt_var_coords_normalized (font, copy, coords_length);
 }
 
 /**
- * hb_font_set_var_coords_normalized:
+ * hb_font_get_var_coords_normalized:
  *
  * Return value is valid as long as variation coordinates of the font
  * are not modified.
  *
  * Since: 1.4.2
  */
 const int *
 hb_font_get_var_coords_normalized (hb_font_t *font,
--- a/gfx/harfbuzz/src/hb-font.h
+++ b/gfx/harfbuzz/src/hb-font.h
@@ -558,16 +558,20 @@ hb_font_is_immutable (hb_font_t *font);
 
 HB_EXTERN void
 hb_font_set_parent (hb_font_t *font,
 		    hb_font_t *parent);
 
 HB_EXTERN hb_font_t *
 hb_font_get_parent (hb_font_t *font);
 
+HB_EXTERN void
+hb_font_set_face (hb_font_t *font,
+		  hb_face_t *face);
+
 HB_EXTERN hb_face_t *
 hb_font_get_face (hb_font_t *font);
 
 
 HB_EXTERN void
 hb_font_set_funcs (hb_font_t         *font,
 		   hb_font_funcs_t   *klass,
 		   void              *font_data,
--- a/gfx/harfbuzz/src/hb-graphite2.cc
+++ b/gfx/harfbuzz/src/hb-graphite2.cc
@@ -22,26 +22,25 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #define HB_SHAPER graphite2
-#define hb_graphite2_shaper_font_data_t gr_font
 #include "hb-shaper-impl-private.hh"
 
 #include "hb-graphite2.h"
 
 #include <graphite2/Segment.h>
 
 
-HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
+HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font)
 
 
 /*
  * shaper face data
  */
 
 typedef struct hb_graphite2_tablelist_t {
   struct hb_graphite2_tablelist_t *next;
@@ -148,46 +147,36 @@ hb_graphite2_face_get_gr_face (hb_face_t
   return HB_SHAPER_DATA_GET (face)->grface;
 }
 
 
 /*
  * shaper font data
  */
 
-static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid)
-{
-  return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid);
-}
+struct hb_graphite2_shaper_font_data_t {};
 
 hb_graphite2_shaper_font_data_t *
-_hb_graphite2_shaper_font_data_create (hb_font_t *font)
+_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL;
-
-  hb_face_t *face = font->face;
-  hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-
-  return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface);
+  return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
+_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
 {
-  gr_font_destroy (data);
 }
 
 /*
  * Since: 0.9.10
  */
 gr_font *
 hb_graphite2_font_get_gr_font (hb_font_t *font)
 {
-  if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
-  return HB_SHAPER_DATA_GET (font);
+  return NULL;
 }
 
 
 /*
  * shaper shape_plan data
  */
 
 struct hb_graphite2_shaper_shape_plan_data_t {};
@@ -225,17 +214,16 @@ hb_bool_t
 _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
 		     hb_font_t          *font,
 		     hb_buffer_t        *buffer,
 		     const hb_feature_t *features,
 		     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
   gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
-  gr_font *grfont = HB_SHAPER_DATA_GET (font);
 
   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   const char *lang_end = lang ? strchr (lang, '-') : NULL;
   int lang_len = lang_end ? lang_end - lang : -1;
   gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
 
   for (unsigned int i = 0; i < num_features; i++)
   {
@@ -257,17 +245,17 @@ hb_bool_t
   for (unsigned int i = 0; i < buffer->len; ++i)
     chars[i] = buffer->info[i].codepoint;
 
   /* TODO ensure_native_direction. */
 
   hb_tag_t script_tag[2];
   hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
 
-  seg = gr_make_seg (grfont, grface,
+  seg = gr_make_seg (NULL, grface,
 		     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
 		     feats,
 		     gr_utf32, chars, buffer->len,
 		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
 
   if (unlikely (!seg)) {
     if (feats) gr_featureval_destroy (feats);
     return false;
@@ -368,58 +356,61 @@ hb_bool_t
       hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
       info->codepoint = gids[clusters[i].base_glyph + j];
       info->cluster = clusters[i].cluster;
       info->var1.i32 = clusters[i].advance;     // all glyphs in the cluster get the same advance
     }
   }
   buffer->len = glyph_count;
 
-  float yscale = font->y_scale / font->x_scale;
+  unsigned int upem = hb_face_get_upem (face);
+  float xscale = (float) font->x_scale / upem;
+  float yscale = (float) font->y_scale / upem;
+  yscale *= yscale / xscale;
   /* Positioning. */
   if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
   {
     int currclus = -1;
     const hb_glyph_info_t *info = buffer->info;
     hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL);
     curradvx = 0;
     for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is))
     {
-      pPos->x_offset = gr_slot_origin_X (is) - curradvx;
+      pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx;
       pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
       if (info->cluster != currclus) {
-        pPos->x_advance = info->var1.i32;
+        pPos->x_advance = info->var1.i32 * xscale;
         curradvx += pPos->x_advance;
         currclus = info->cluster;
       } else
         pPos->x_advance = 0.;
 
-      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
+      pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale;
       curradvy += pPos->y_advance;
     }
   }
   else
   {
     int currclus = -1;
     const hb_glyph_info_t *info = buffer->info;
     hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL);
-    curradvx = gr_seg_advance_X(seg);
+    curradvx = gr_seg_advance_X(seg) * xscale;
     for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is))
     {
       if (info->cluster != currclus)
       {
-        pPos->x_advance = info->var1.i32;
-        if (currclus != -1) curradvx -= info[-1].var1.i32;
+        pPos->x_advance = info->var1.i32 * xscale;
+        if (currclus != -1) curradvx -= info[-1].var1.i32 * xscale;
         currclus = info->cluster;
       } else
       pPos->x_advance = 0.;
 
-      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
+      pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale;
       curradvy -= pPos->y_advance;
-      pPos->x_offset = gr_slot_origin_X (is) - curradvx + pPos->x_advance;
+      pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx + pPos->x_advance;
       pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
     }
     hb_buffer_reverse_clusters (buffer);
   }
 
   if (feats) gr_featureval_destroy (feats);
   gr_seg_destroy (seg);
 
--- a/gfx/harfbuzz/src/hb-graphite2.h
+++ b/gfx/harfbuzz/src/hb-graphite2.h
@@ -34,15 +34,19 @@ HB_BEGIN_DECLS
 
 
 #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
 
 
 HB_EXTERN gr_face *
 hb_graphite2_face_get_gr_face (hb_face_t *face);
 
+#ifndef HB_DISABLE_DEPRECATED
+
 HB_EXTERN gr_font *
 hb_graphite2_font_get_gr_font (hb_font_t *font);
 
+#endif
+
 
 HB_END_DECLS
 
 #endif /* HB_GRAPHITE2_H */
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -618,10 +618,9 @@ static inline void
 }
 
 /* Make sure no one directly touches our props... */
 #undef unicode_props0
 #undef unicode_props1
 #undef lig_props
 #undef glyph_props
 
-
 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -34,18 +34,16 @@
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
 
 #include "hb-ot-map-private.hh"
 
 
-HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
-
 hb_ot_layout_t *
 _hb_ot_layout_create (hb_face_t *face)
 {
   hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
   if (unlikely (!layout))
     return NULL;
 
   layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
@@ -130,16 +128,19 @@ hb_ot_layout_t *
       /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
       || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
       /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
       || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
       /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
       || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
       /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
       || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
+      /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
+       *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+      || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
     )
     {
       /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
        * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
        * and the version of Cantarell shipped by Ubuntu 16.04.
        * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
        * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
        *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
--- a/gfx/harfbuzz/src/hb-ot-math.cc
+++ b/gfx/harfbuzz/src/hb-ot-math.cc
@@ -21,20 +21,19 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Igalia Author(s): Frédéric Wang
  */
 
 #include "hb-open-type-private.hh"
 
+#include "hb-ot-layout-private.hh"
 #include "hb-ot-math-table.hh"
 
-HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
-
 static inline const OT::MATH&
 _get_math (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
   return *(layout->math.get ());
 }
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -535,17 +535,17 @@ apply_stch (const hb_ot_shape_plan_t *pl
 
       hb_position_t w_remaining = w_total - w_fixed;
       if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
 	n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
 
       /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
       hb_position_t extra_repeat_overlap = 0;
       hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
-      if (shortfall > 0)
+      if (shortfall > 0 && n_repeating > 0)
       {
         ++n_copies;
         hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
         if (excess > 0)
           extra_repeat_overlap = excess / (n_copies * n_repeating);
       }
 
       if (step == MEASURE)
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
@@ -417,16 +417,23 @@ hb_indic_get_categories (hb_codepoint_t 
       break;
 
     case 0xAu:
       if (hb_in_range (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
       if (hb_in_range (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
       if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
       break;
 
+    case 0x11u:
+      // According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
+      // so the Indic shaper needs to know their categories.
+      if (unlikely (u == 0x11303)) return _(Vs,R);
+      if (unlikely (u == 0x1133c)) return _(N,B);
+      break;
+
     default:
       break;
   }
   return _(x,x);
 }
 
 #undef _
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
@@ -186,16 +186,19 @@ hb_ot_shape_complex_categorize (const hb
 
     /* Unicode-6.0 additions */
     case HB_SCRIPT_MANDAIC:
 
     /* Unicode-7.0 additions */
     case HB_SCRIPT_MANICHAEAN:
     case HB_SCRIPT_PSALTER_PAHLAVI:
 
+    /* Unicode-9.0 additions */
+    case HB_SCRIPT_ADLAM:
+
       /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
        * This is because we do fallback shaping for Arabic script (and not others).
        * But note that Arabic shaping is applicable only to horizontal layout; for
        * vertical text, just use the generic shaper instead. */
       if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
 	   planner->props.script == HB_SCRIPT_ARABIC) &&
 	  HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
 	return &_hb_ot_complex_shaper_arabic;
--- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -86,17 +86,17 @@ compose_unicode (const hb_ot_shape_norma
 		 hb_codepoint_t *ab)
 {
   return (bool) c->unicode->compose (a, b, ab);
 }
 
 static inline void
 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
 {
-  font->get_nominal_glyph (info.codepoint, &info.glyph_index());
+  (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index());
 }
 
 static inline void
 output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
 {
   buffer->cur().glyph_index() = glyph;
   buffer->output_glyph (unichar); /* This is very confusing indeed. */
   _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -123,16 +123,18 @@ hb_ot_shape_collect_features (hb_ot_shap
   }
 }
 
 
 /*
  * shaper face data
  */
 
+HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
+
 hb_ot_shaper_face_data_t *
 _hb_ot_shaper_face_data_create (hb_face_t *face)
 {
   return _hb_ot_layout_create (face);
 }
 
 void
 _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
@@ -140,16 +142,18 @@ void
   _hb_ot_layout_destroy (data);
 }
 
 
 /*
  * shaper font data
  */
 
+HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
+
 struct hb_ot_shaper_font_data_t {};
 
 hb_ot_shaper_font_data_t *
 _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
   return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
--- a/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
@@ -73,20 +73,20 @@ struct DeltaSetIndexMap
   protected:
   inline unsigned int get_width (void) const
   { return ((format >> 4) & 3) + 1; }
 
   inline unsigned int get_inner_bitcount (void) const
   { return (format & 0xF) + 1; }
 
   protected:
-  USHORT format;		/* A packed field that describes the compressed
+  USHORT	format;		/* A packed field that describes the compressed
 				 * representation of delta-set indices. */
-  USHORT mapCount;		/* The number of mapping entries. */
-  BYTE mapData[VAR];		/* The delta-set index mapping data. */
+  USHORT	mapCount;	/* The number of mapping entries. */
+  BYTE		mapData[VAR];	/* The delta-set index mapping data. */
 
   public:
   DEFINE_SIZE_ARRAY (4, mapData);
 };
 
 
 /*
  * HVAR -- The Horizontal Metrics Variations Table
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_VAR_MVAR_TABLE_HH
+#define HB_OT_VAR_MVAR_TABLE_HH
+
+#include "hb-ot-layout-common-private.hh"
+
+
+namespace OT {
+
+
+struct VariationValueRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  Tag		valueTag;	/* Four-byte tag identifying a font-wide measure. */
+  ULONG		varIdx;		/* Outer/inner index into VariationStore item. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+
+/*
+ * MVAR -- Metrics Variations Table
+ */
+
+#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R')
+
+struct MVAR
+{
+  static const hb_tag_t tableTag	= HB_OT_TAG_MVAR;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+		  likely (version.major == 1) &&
+		  c->check_struct (this) &&
+		  valueRecordSize >= VariationValueRecord::static_size &&
+		  varStore.sanitize (c, this) &&
+		  c->check_array (values, valueRecordSize, valueRecordCount));
+  }
+
+  inline float get_var (hb_tag_t tag,
+			int *coords, unsigned int coord_count) const
+  {
+    const VariationValueRecord *record;
+    record = (VariationValueRecord *) bsearch (&tag, values,
+					       valueRecordCount, valueRecordSize,
+					       (hb_compare_func_t) tag_compare);
+    if (!record)
+      return 0.;
+
+    return (this+varStore).get_delta (record->varIdx, coords, coord_count);
+  }
+
+protected:
+  static inline int tag_compare (const hb_tag_t *a, const Tag *b)
+  { return b->cmp (*a); }
+
+  protected:
+  FixedVersion<>version;	/* Version of the metrics variation table
+				 * initially set to 0x00010000u */
+  USHORT	reserved;	/* Not used; set to 0. */
+  USHORT	valueRecordSize;/* The size in bytes of each value record —
+				 * must be greater than zero. */
+  USHORT	valueRecordCount;/* The number of value records — may be zero. */
+  OffsetTo<VariationStore>
+		varStore;	/* Offset to item variation store table. */
+  BYTE		values[VAR];	/* Array of value records. The records must be
+				 * in binary order of their valueTag field. */
+
+  public:
+  DEFINE_SIZE_ARRAY (12, values);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_VAR_MVAR_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-var.cc
+++ b/gfx/harfbuzz/src/hb-ot-var.cc
@@ -24,20 +24,19 @@
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb-open-type-private.hh"
 
 #include "hb-ot-layout-private.hh"
 #include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
+#include "hb-ot-var-mvar-table.hh"
 #include "hb-ot-var.h"
 
-HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
-
 /*
  * fvar/avar
  */
 
 static inline const OT::fvar&
 _get_fvar (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar);
--- a/gfx/harfbuzz/src/hb-shape-plan.cc
+++ b/gfx/harfbuzz/src/hb-shape-plan.cc
@@ -30,23 +30,16 @@
 #include "hb-buffer-private.hh"
 
 
 #ifndef HB_DEBUG_SHAPE_PLAN
 #define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
 #endif
 
 
-#define HB_SHAPER_IMPLEMENT(shaper) \
-	HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \
-	HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font)
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-
 static void
 hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
 		    const hb_feature_t *user_features,
 		    unsigned int        num_user_features,
 		    const int          *coords,
 		    unsigned int        num_coords,
 		    const char * const *shaper_list)
 {
--- a/gfx/harfbuzz/src/hb-shaper-private.hh
+++ b/gfx/harfbuzz/src/hb-shaper-private.hh
@@ -60,37 +60,41 @@ struct hb_shaper_data_t {
 
 /* Means: succeeded, but don't need to keep any data. */
 #define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
 
 /* Means: tried but failed to create. */
 #define HB_SHAPER_DATA_INVALID ((void *) -1)
 #define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
 
-#define HB_SHAPER_DATA_TYPE(shaper, object)		struct hb_##shaper##_shaper_##object##_data_t
+#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)	hb_##shaper##_shaper_##object##_data_t
+#define HB_SHAPER_DATA_TYPE(shaper, object)		struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
 #define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)	(* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
-#define HB_SHAPER_DATA(shaper, object)			HB_SHAPER_DATA_INSTANCE (shaper, object, object)
+#define HB_SHAPER_DATA(shaper, object)			HB_SHAPER_DATA_INSTANCE(shaper, object, object)
 #define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_create
 #define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_destroy
+#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)	hb_##shaper##_shaper_##object##_data_ensure
 
 #define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
 	HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
 	extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
 	HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
 	extern "C" HB_INTERNAL void \
-	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data)
+	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
+	extern "C" HB_INTERNAL bool \
+	HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
 
 #define HB_SHAPER_DATA_DESTROY(shaper, object) \
     if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
       if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
         HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
 
-#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \
-static inline bool \
-hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \
+#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
+bool \
+HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
 {\
   retry: \
   HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
   if (unlikely (!data)) { \
     data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
     if (unlikely (!data)) \
       data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
     if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), NULL, data)) { \
--- a/gfx/harfbuzz/src/hb-uniscribe.cc
+++ b/gfx/harfbuzz/src/hb-uniscribe.cc
@@ -288,18 +288,18 @@ struct feature_event_t {
 };
 
 struct range_record_t {
   TEXTRANGE_PROPERTIES props;
   unsigned int index_first; /* == start */
   unsigned int index_last;  /* == end - 1 */
 };
 
-HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
+HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face)
+HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
 
 
 /*
  * shaper face data
  */
 
 struct hb_uniscribe_shaper_face_data_t {
   HANDLE fh;
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 4
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MICRO 3
 
-#define HB_VERSION_STRING "1.4.2"
+#define HB_VERSION_STRING "1.4.3"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/harfbuzz/src/moz.build
+++ b/gfx/harfbuzz/src/moz.build
@@ -35,17 +35,16 @@ SOURCES += [
     'hb-ot-shape-complex-use.cc', # error: redefinition of 'basic_features'
     'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded
     'hb-shape-plan.cc', # error: redefinition of 'hb_ot_shaper_face_data_ensure'
 ]
 
 UNIFIED_SOURCES += [
     'hb-buffer.cc',
     'hb-face.cc',
-    'hb-fallback-shape.cc',
     'hb-font.cc',
     'hb-ot-layout.cc',
     'hb-ot-map.cc',
     'hb-ot-shape-complex-arabic.cc',
     'hb-ot-shape-complex-default.cc',
     'hb-ot-shape-complex-hebrew.cc',
     'hb-ot-shape-complex-indic-table.cc',
     'hb-ot-shape-complex-myanmar.cc',
--- a/gfx/layers/ipc/UiCompositorControllerChild.cpp
+++ b/gfx/layers/ipc/UiCompositorControllerChild.cpp
@@ -54,17 +54,17 @@ DoCachedResize()
 {
   MOZ_ASSERT(sChild);
   MOZ_ASSERT(sChild->IsOnUiThread());
 
   for (auto& cache : sResizeCache) {
     sChild->SendResumeAndResize(cache.first, cache.second.mSurfaceWidth, cache.second.mSurfaceHeight);
   }
 
-  sResizeCache.empty();
+  sResizeCache.clear();
 }
 
 } // namespace
 
 UiCompositorControllerChild::UiCompositorControllerChild(RefPtr<nsThread> aThread, const uint64_t& aProcessToken)
  : mUiThread(aThread),
    mProcessToken(aProcessToken)
 {
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -9,21 +9,17 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
 
 #include "gfxTypes.h"
 #include "nscore.h"
 #include "nsSize.h"
 #include "mozilla/gfx/Rect.h"
 
-#ifdef MOZILLA_INTERNAL_API
 #include "nsStringFwd.h"
-#else
-#include "nsStringAPI.h"
-#endif
 
 class gfxImageSurface;
 struct gfxRect;
 struct gfxPoint;
 
 template <typename T>
 struct already_AddRefed;
 
deleted file mode 100644
--- a/intl/unicharutil/util/internal/moz.build
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=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/.
-
-# This file builds the version of unicharutils_s static library which uses
-# internal linkage. Components that use frozen (external) linkage should use
-# unicharutil_external_s.
-
-include('../objs.mozbuild')
-
-UNIFIED_SOURCES += intl_unicharutil_util_cppsrcs
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
-    '..',
-]
-
-DIST_INSTALL = True
--- a/intl/unicharutil/util/moz.build
+++ b/intl/unicharutil/util/moz.build
@@ -1,43 +1,32 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
-# This file builds the unicharutil_external_s library which should be used
-# by frozen (dependent) linkage components. Internal-linkage code should use
-# unicharutil_s which is built in the internal/ subdirectory.
-
-DIRS += ['internal']
-
 EXPORTS += [
     'GreekCasing.h',
     'ICUUtils.h',
     'IrishCasing.h',
     'nsBidiUtils.h',
     'nsSpecialCasingData.h',
     'nsUnicharUtils.h',
     'nsUnicodeProperties.h',
     'nsUnicodeScriptCodes.h',
 ]
 
-include('objs.mozbuild')
-
-UNIFIED_SOURCES += intl_unicharutil_util_cppsrcs
-
-Library('unicharutil_external_s')
-
-FORCE_STATIC_LIB = True
-
-USE_STATIC_LIBS = True
-
-if CONFIG['_MSC_VER']:
-    DEFINES['_USE_ANSI_CPP'] = True
-    # Don't include directives about which CRT to use
-    CFLAGS += ['-Zl']
-    CXXFLAGS += ['-Zl']
+UNIFIED_SOURCES += [
+    'GreekCasing.cpp',
+    'IrishCasing.cpp',
+    'nsBidiUtils.cpp',
+    'nsSpecialCasingData.cpp',
+    'nsUnicharUtils.cpp',
+    'nsUnicodeProperties.cpp',
+]
 
 if CONFIG['ENABLE_INTL_API']:
-    USE_LIBS += ['icu']
+    UNIFIED_SOURCES += [
+        'ICUUtils.cpp',
+    ]
 
-DIST_INSTALL = True
+FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/intl/unicharutil/util/objs.mozbuild
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=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/.
-
-intl_unicharutil_util_lcppsrcs = [
-    'GreekCasing.cpp',
-]
-
-if CONFIG['ENABLE_INTL_API']:
-    intl_unicharutil_util_lcppsrcs += [
-        'ICUUtils.cpp',
-    ]
-
-intl_unicharutil_util_lcppsrcs += [
-    'IrishCasing.cpp',
-    'nsBidiUtils.cpp',
-    'nsSpecialCasingData.cpp',
-    'nsUnicharUtils.cpp',
-    'nsUnicodeProperties.cpp',
-]
-
-intl_unicharutil_util_cppsrcs = [
-    '/intl/unicharutil/util/%s' % s
-        for s in intl_unicharutil_util_lcppsrcs
-]
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -6,21 +6,21 @@
 
 
 #include "builtin/Promise.h"
 
 #include "mozilla/Atomics.h"
 #include "mozilla/TimeStamp.h"
 
 #include "jscntxt.h"
+#include "jsexn.h"
 
 #include "gc/Heap.h"
 #include "js/Debug.h"
 #include "vm/AsyncFunction.h"
-#include "vm/SelfHosting.h"
 
 #include "jsobjinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 static double
@@ -29,18 +29,18 @@ MillisecondsSinceStartup()
     auto now = mozilla::TimeStamp::Now();
     bool ignored;
     return (now - mozilla::TimeStamp::ProcessCreation(ignored)).ToMilliseconds();
 }
 
 enum PromiseHandler {
     PromiseHandlerIdentity = 0,
     PromiseHandlerThrower,
-    PromiseHandlerAwaitFulfilled,
-    PromiseHandlerAwaitRejected,
+    PromiseHandlerAsyncFunctionAwaitFulfilled,
+    PromiseHandlerAsyncFunctionAwaitRejected,
 };
 
 enum ResolutionMode {
     ResolveMode,
     RejectMode
 };
 
 enum ResolveFunctionSlots {
@@ -169,17 +169,17 @@ enum ReactionRecordSlots {
     ReactionRecordSlot_Flags,
     ReactionRecordSlot_HandlerArg,
     ReactionRecordSlots,
 };
 
 #define REACTION_FLAG_RESOLVED                  0x1
 #define REACTION_FLAG_FULFILLED                 0x2
 #define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
-#define REACTION_FLAG_AWAIT                     0x8
+#define REACTION_FLAG_ASYNC_FUNCTION_AWAIT      0x8
 
 // ES2016, 25.4.1.2.
 class PromiseReactionRecord : public NativeObject
 {
   public:
     static const Class class_;
 
     JSObject* promise() { return getFixedSlot(ReactionRecordSlot_Promise).toObjectOrNull(); }
@@ -196,24 +196,24 @@ class PromiseReactionRecord : public Nat
         int32_t flags = this->flags();
         MOZ_ASSERT(!(flags & REACTION_FLAG_RESOLVED));
         MOZ_ASSERT(state != JS::PromiseState::Pending, "Can't revert a reaction to pending.");
         flags |= REACTION_FLAG_RESOLVED;
         if (state == JS::PromiseState::Fulfilled)
             flags |= REACTION_FLAG_FULFILLED;
         setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
     }
-    void setIsAwait() {
+    void setIsAsyncFunctionAwait() {
         int32_t flags = this->flags();
-        flags |= REACTION_FLAG_AWAIT;
+        flags |= REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
         setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
     }
-    bool isAwait() {
+    bool isAsyncFunctionAwait() {
         int32_t flags = this->flags();
-        return flags & REACTION_FLAG_AWAIT;
+        return flags & REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
     }
     Value handler() {
         MOZ_ASSERT(targetState() != JS::PromiseState::Pending);
         uint32_t slot = targetState() == JS::PromiseState::Fulfilled
                         ? ReactionRecordSlot_OnFulfilled
                         : ReactionRecordSlot_OnRejected;
         return getFixedSlot(slot);
     }
@@ -765,19 +765,17 @@ RejectMaybeWrappedPromise(JSContext *cx,
         // rejection handler.
         if (!promise->compartment()->wrap(cx, &reason))
             return false;
         if (reason.isObject() && !CheckedUnwrap(&reason.toObject())) {
             // Async stacks are only properly adopted if there's at least one
             // interpreter frame active right now. If a thenable job with a
             // throwing `then` function got us here, that'll not be the case,
             // so we add one by throwing the error from self-hosted code.
-            FixedInvokeArgs<1> getErrorArgs(cx);
-            getErrorArgs[0].set(Int32Value(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON));
-            if (!CallSelfHostedFunction(cx, "GetInternalError", reason, getErrorArgs, &reason))
+            if (!GetInternalError(cx, JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON, &reason))
                 return false;
         }
     }
 
     MOZ_ASSERT(promise->state() == JS::PromiseState::Pending);
 
     return ResolvePromise(cx, promise, reason, JS::PromiseState::Rejected);
 }
@@ -802,33 +800,33 @@ TriggerPromiseReactions(JSContext* cx, H
         if (!EnqueuePromiseReactionJob(cx, reaction, valueOrReason, state))
             return false;
     }
 
     return true;
 }
 
 static MOZ_MUST_USE bool
-AwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
-                        MutableHandleValue rval)
+AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
+                                     MutableHandleValue rval)
 {
-    MOZ_ASSERT(reaction->isAwait());
+    MOZ_ASSERT(reaction->isAsyncFunctionAwait());
 
     RootedValue handlerVal(cx, reaction->handler());
     RootedValue argument(cx, reaction->handlerArg());
     Rooted<PromiseObject*> resultPromise(cx, &reaction->promise()->as<PromiseObject>());
     RootedValue generatorVal(cx, resultPromise->getFixedSlot(PromiseSlot_AwaitGenerator));
 
     int32_t handlerNum = int32_t(handlerVal.toNumber());
-    MOZ_ASSERT(handlerNum == PromiseHandlerAwaitFulfilled
-               || handlerNum == PromiseHandlerAwaitRejected);
+    MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFunctionAwaitFulfilled ||
+               handlerNum == PromiseHandlerAsyncFunctionAwaitRejected);
 
     // Await's handlers don't return a value, nor throw exception.
     // They fail only on OOM.
-    if (handlerNum == PromiseHandlerAwaitFulfilled) {
+    if (handlerNum == PromiseHandlerAsyncFunctionAwaitFulfilled) {
         if (!AsyncFunctionAwaitedFulfilled(cx, resultPromise, generatorVal, argument))
             return false;
     } else {
         if (!AsyncFunctionAwaitedRejected(cx, resultPromise, generatorVal, argument))
             return false;
     }
 
     rval.setUndefined();
@@ -866,18 +864,18 @@ PromiseReactionJob(JSContext* cx, unsign
     mozilla::Maybe<AutoCompartment> ac;
     if (IsWrapper(reactionObj)) {
         reactionObj = UncheckedUnwrap(reactionObj);
         ac.emplace(cx, reactionObj);
     }
 
     // Steps 1-2.
     Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
-    if (reaction->isAwait())
-        return AwaitPromiseReactionJob(cx, reaction, args.rval());
+    if (reaction->isAsyncFunctionAwait())
+        return AsyncFunctionAwaitPromiseReactionJob(cx, reaction, args.rval());
 
     // Step 3.
     RootedValue handlerVal(cx, reaction->handler());
 
     RootedValue argument(cx, reaction->handlerArg());
 
     RootedValue handlerResult(cx);
     ResolutionMode resolutionMode = ResolveMode;
@@ -2164,32 +2162,32 @@ js::AsyncFunctionAwait(JSContext* cx, Ha
     if (!promise)
         return false;
 
     // Steps 3.
     if (!ResolvePromiseInternal(cx, promise, value))
         return false;
 
     // Steps 4-5.
-    RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAwaitFulfilled));
-    RootedValue onRejected(cx, Int32Value(PromiseHandlerAwaitRejected));
+    RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitFulfilled));
+    RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitRejected));
 
     RootedObject incumbentGlobal(cx);
     if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
         return false;
 
     // Steps 6-7.
     Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise,
                                                                   onFulfilled, onRejected,
                                                                   nullptr, nullptr,
                                                                   incumbentGlobal));
     if (!reaction)
         return false;
 
-    reaction->setIsAwait();
+    reaction->setIsAsyncFunctionAwait();
 
     // Step 8.
     return PerformPromiseThenWithReaction(cx, promise, reaction);
 }
 
 // ES2016, 25.4.5.3.
 bool
 js::Promise_then(JSContext* cx, unsigned argc, Value* vp)
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -2797,21 +2797,21 @@ ASTSerializer::generatorExpression(Parse
             next = next->pn_kid2;
         } else {
             break;
         }
     }
 
     LOCAL_ASSERT(next->isKind(PNK_SEMI) &&
                  next->pn_kid->isKind(PNK_YIELD) &&
-                 next->pn_kid->pn_left);
+                 next->pn_kid->pn_kid);
 
     RootedValue body(cx);
 
-    return expression(next->pn_kid->pn_left, &body) &&
+    return expression(next->pn_kid->pn_kid, &body) &&
            builder.generatorExpression(body, blocks, filter, isLegacy, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
 {
     if (!CheckRecursionLimit(cx))
         return false;
@@ -3145,29 +3145,29 @@ ASTSerializer::expression(ParseNode* pn,
       case PNK_TRUE:
       case PNK_FALSE:
       case PNK_NULL:
       case PNK_RAW_UNDEFINED:
         return literal(pn, dst);
 
       case PNK_YIELD_STAR:
       {
-        MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
+        MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
-        return expression(pn->pn_left, &arg) &&
+        return expression(pn->pn_kid, &arg) &&
                builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst);
       }
 
       case PNK_YIELD:
       {
-        MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos));
+        MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
-        return optExpression(pn->pn_left, &arg) &&
+        return optExpression(pn->pn_kid, &arg) &&
                builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst);
       }
 
       case PNK_ARRAYCOMP:
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_head->pn_pos));
 
         /* NB: it's no longer the case that pn_count could be 2. */
         LOCAL_ASSERT(pn->pn_count == 1);
@@ -3411,20 +3411,20 @@ ASTSerializer::identifier(ParseNode* pn,
 }
 
 bool
 ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
 {
     RootedFunction func(cx, pn->pn_funbox->function());
 
     GeneratorStyle generatorStyle =
-        pn->pn_funbox->isGenerator()
-        ? (pn->pn_funbox->isLegacyGenerator()
-           ? GeneratorStyle::Legacy
-           : GeneratorStyle::ES6)
+        pn->pn_funbox->isStarGenerator()
+        ? GeneratorStyle::ES6
+        : pn->pn_funbox->isLegacyGenerator()
+        ? GeneratorStyle::Legacy
         : GeneratorStyle::None;
 
     bool isAsync = pn->pn_funbox->isAsync();
     bool isExpression = pn->pn_funbox->isExprBody();
 
     RootedValue id(cx);
     RootedAtom funcAtom(cx, func->explicitName());
     if (!optIdentifier(funcAtom, nullptr, &id))
@@ -3469,17 +3469,17 @@ ASTSerializer::functionArgsAndBody(Parse
         return functionArgs(pn, pnargs, args, defaults, rest) &&
                expression(pnbody->pn_kid, body);
 
       case PNK_STATEMENTLIST:     /* statement closure */
       {
         ParseNode* pnstart = pnbody->pn_head;
 
         // Skip over initial yield in generator.
-        if (pnstart && pnstart->isKind(PNK_YIELD)) {
+        if (pnstart && pnstart->isKind(PNK_INITIALYIELD)) {
             MOZ_ASSERT(pnstart->getOp() == JSOP_INITIALYIELD);
             pnstart = pnstart->pn_next;
         }
 
         // Async arrow with expression body is converted into STATEMENTLIST
         // to insert initial yield.
         if (isAsync && isExpression) {
             MOZ_ASSERT(pnstart->getKind() == PNK_RETURN);
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -747,10 +747,10 @@ bool
 frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun,
                                          const ReadOnlyCompileOptions& options,
                                          JS::SourceBufferHolder& srcBuf,
                                          const Maybe<uint32_t>& parameterListEnd)
 {
     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
 
     BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
-    return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd);
+    return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd);
 }
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -384,17 +384,20 @@ class BytecodeEmitter::EmitterScope : pu
         environmentChainLength_ = mozilla::AssertedCast<uint8_t>(hops + 1);
         return true;
     }
 
     void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi) {
         nextFrameSlot_ = bi.nextFrameSlot();
         if (nextFrameSlot_ > bce->maxFixedSlots)
             bce->maxFixedSlots = nextFrameSlot_;
-        MOZ_ASSERT_IF(bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator(),
+        MOZ_ASSERT_IF(bce->sc->isFunctionBox() &&
+                      (bce->sc->asFunctionBox()->isStarGenerator() ||
+                       bce->sc->asFunctionBox()->isLegacyGenerator() ||
+                       bce->sc->asFunctionBox()->isAsync()),
                       bce->maxFixedSlots == 0);
     }
 
     MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc) {
         NameLocationMap& cache = *nameCache_;
         NameLocationMap::AddPtr p = cache.lookupForAdd(name);
         MOZ_ASSERT(!p);
         if (!cache.add(p, name, loc)) {
@@ -2161,17 +2164,17 @@ BytecodeEmitter::BytecodeEmitter(Bytecod
     varEmitterScope(nullptr),
     innermostNestableControl(nullptr),
     innermostEmitterScope(nullptr),
     innermostTDZCheckCache(nullptr),
     constList(cx),
     scopeList(cx),
     tryNoteList(cx),
     scopeNoteList(cx),
-    yieldOffsetList(cx),
+    yieldAndAwaitOffsetList(cx),
     typesetCount(0),
     hasSingletons(false),
     hasTryFinally(false),
     emittingRunOnceLambda(false),
     emitterMode(emitterMode),
     functionBodyEndPosSet(false)
 {
     MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
@@ -3155,20 +3158,21 @@ BytecodeEmitter::checkSideEffects(ParseN
         return true;
 
       // This invokes the (user-controllable) iterator protocol.
       case PNK_SPREAD:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
+      case PNK_INITIALYIELD:
       case PNK_YIELD_STAR:
       case PNK_YIELD:
       case PNK_AWAIT:
-        MOZ_ASSERT(pn->isArity(PN_BINARY));
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // Deletion generally has side effects, even if isolated cases have none.
       case PNK_DELETENAME:
       case PNK_DELETEPROP:
       case PNK_DELETEELEM:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
@@ -4786,41 +4790,43 @@ BytecodeEmitter::isRunOnceLambda()
     if (!(parent && parent->emittingRunOnceLambda) &&
         (emitterMode != LazyFunction || !lazyScript->treatAsRunOnce()))
     {
         return false;
     }
 
     FunctionBox* funbox = sc->asFunctionBox();
     return !funbox->argumentsHasLocalBinding() &&
-           !funbox->isGenerator() &&
+           !funbox->isStarGenerator() &&
+           !funbox->isLegacyGenerator() &&
+           !funbox->isAsync() &&
            !funbox->function()->explicitName();
 }
 
 bool
 BytecodeEmitter::emitYieldOp(JSOp op)
 {
     if (op == JSOP_FINALYIELDRVAL)
         return emit1(JSOP_FINALYIELDRVAL);
 
-    MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD);
+    MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD || op == JSOP_AWAIT);
 
     ptrdiff_t off;
     if (!emitN(op, 3, &off))
         return false;
 
-    uint32_t yieldIndex = yieldOffsetList.length();
-    if (yieldIndex >= JS_BIT(24)) {
+    uint32_t yieldAndAwaitIndex = yieldAndAwaitOffsetList.length();
+    if (yieldAndAwaitIndex >= JS_BIT(24)) {
         reportError(nullptr, JSMSG_TOO_MANY_YIELDS);
         return false;
     }
 
-    SET_UINT24(code(off), yieldIndex);
-
-    if (!yieldOffsetList.append(offset()))
+    SET_UINT24(code(off), yieldAndAwaitIndex);
+
+    if (!yieldAndAwaitOffsetList.append(offset()))
         return false;
 
     return emit1(JSOP_DEBUGAFTERYIELD);
 }
 
 bool
 BytecodeEmitter::emitSetThis(ParseNode* pn)
 {
@@ -8236,32 +8242,33 @@ BytecodeEmitter::emitCheckDerivedClassCo
 }
 
 bool
 BytecodeEmitter::emitReturn(ParseNode* pn)
 {
     if (!updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
 
-    if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
+    bool needsIteratorResult = sc->isFunctionBox() && sc->asFunctionBox()->needsIteratorResult();
+    if (needsIteratorResult) {
         if (!emitPrepareIteratorResult())
             return false;
     }
 
     /* Push a return value */
     if (ParseNode* pn2 = pn->pn_kid) {
         if (!emitTree(pn2))
             return false;
     } else {
         /* No explicit return value provided */
         if (!emit1(JSOP_UNDEFINED))
             return false;
     }
 
-    if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
+    if (needsIteratorResult) {
         if (!emitFinishIteratorResult(true))
             return false;
     }
 
     // We know functionBodyEndPos is set because "return" is only
     // valid in a function, and so we've passed through
     // emitFunctionScript.
     MOZ_ASSERT(functionBodyEndPosSet);
@@ -8276,36 +8283,36 @@ BytecodeEmitter::emitReturn(ParseNode* p
      * with the correct stack pointer (i.e., after popping any with,
      * for/in, etc., slots nested inside the finally's try).
      *
      * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
      * extra JSOP_RETRVAL after the fixups.
      */
     ptrdiff_t top = offset();
 
-    bool isGenerator = sc->isFunctionBox() && sc->asFunctionBox()->isGenerator();
+    bool needsFinalYield = sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
     bool isDerivedClassConstructor =
         sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
 
-    if (!emit1((isGenerator || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
+    if (!emit1((needsFinalYield || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
         return false;
 
     // Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
     // to ensure that the error is thrown while the scope-chain is still intact.
     if (isDerivedClassConstructor) {
         if (!emitCheckDerivedClassConstructorReturn())
             return false;
     }
 
     NonLocalExitControl nle(this, NonLocalExitControl::Return);
 
     if (!nle.prepareForNonLocalJumpToOutermost())
         return false;
 
-    if (isGenerator) {
+    if (needsFinalYield) {
         // We know that .generator is on the function scope, as we just exited
         // all nested scopes.
         NameLocation loc =
             *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, varEmitterScope);
         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
             return false;
         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
             return false;
@@ -8318,54 +8325,71 @@ BytecodeEmitter::emitReturn(ParseNode* p
         if (!emit1(JSOP_RETRVAL))
             return false;
     }
 
     return true;
 }
 
 bool
+BytecodeEmitter::emitGetDotGenerator()
+{
+    NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator);
+    return emitGetNameAtLocation(cx->names().dotGenerator, loc);
+}
+
+bool
+BytecodeEmitter::emitInitialYield(ParseNode* pn)
+{
+    if (!emitTree(pn->pn_kid))
+        return false;
+
+    if (!emitYieldOp(JSOP_INITIALYIELD))
+        return false;
+
+    if (!emit1(JSOP_POP))
+        return false;
+
+    return true;
+}
+
+bool
 BytecodeEmitter::emitYield(ParseNode* pn)
 {
     MOZ_ASSERT(sc->isFunctionBox());
-
-    if (pn->getOp() == JSOP_YIELD) {
-        if (sc->asFunctionBox()->isStarGenerator()) {
-            if (!emitPrepareIteratorResult())
-                return false;
-        }
-        if (pn->pn_left) {
-            if (!emitTree(pn->pn_left))
-                return false;
-        } else {
-            if (!emit1(JSOP_UNDEFINED))
-                return false;
-        }
-        if (sc->asFunctionBox()->isStarGenerator()) {
-            if (!emitFinishIteratorResult(false))
-                return false;
-        }
+    MOZ_ASSERT(pn->getOp() == JSOP_YIELD || pn->getOp() == JSOP_AWAIT);
+
+    bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
+    if (needsIteratorResult) {
+        if (!emitPrepareIteratorResult())
+            return false;
+    }
+    if (pn->pn_kid) {
+        if (!emitTree(pn->pn_kid))
+            return false;
     } else {
-        MOZ_ASSERT(pn->getOp() == JSOP_INITIALYIELD);
-    }
-
-    if (!emitTree(pn->pn_right))
+        if (!emit1(JSOP_UNDEFINED))
+            return false;
+    }
+    if (needsIteratorResult) {
+        if (!emitFinishIteratorResult(false))
+            return false;
+    }
+
+    if (!emitGetDotGenerator())
         return false;
 
     if (!emitYieldOp(pn->getOp()))
         return false;
 
-    if (pn->getOp() == JSOP_INITIALYIELD && !emit1(JSOP_POP))
-        return false;
-
-    return true;
-}
-
-bool
-BytecodeEmitter::emitYieldStar(ParseNode* iter, ParseNode* gen)
+    return true;
+}
+
+bool
+BytecodeEmitter::emitYieldStar(ParseNode* iter)
 {
     MOZ_ASSERT(sc->isFunctionBox());
     MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator());
 
     if (!emitTree(iter))                                  // ITERABLE
         return false;
     if (!emitIterator())                                  // ITER
         return false;
@@ -8385,17 +8409,17 @@ BytecodeEmitter::emitYieldStar(ParseNode
 
     JumpTarget tryStart{ offset() };
     if (!tryCatch.emitTry())                              // ITER RESULT
         return false;
 
     MOZ_ASSERT(this->stackDepth == startDepth);
 
     // Load the generator object.
-    if (!emitTree(gen))                                   // ITER RESULT GENOBJ
+    if (!emitGetDotGenerator())                           // ITER RESULT GENOBJ
         return false;
 
     // Yield RESULT as-is, without re-boxing.
     if (!emitYieldOp(JSOP_YIELD))                         // ITER RECEIVED
         return false;
 
     if (!tryCatch.emitCatch())                            // ITER RESULT
         return false;
@@ -10085,32 +10109,36 @@ BytecodeEmitter::emitInitializeFunctionS
 bool
 BytecodeEmitter::emitFunctionBody(ParseNode* funBody)
 {
     FunctionBox* funbox = sc->asFunctionBox();
 
     if (!emitTree(funBody))
         return false;
 
-    if (funbox->isGenerator()) {
+    if (funbox->needsFinalYield()) {
         // If we fall off the end of a generator, do a final yield.
-        if (funbox->isStarGenerator() && !emitPrepareIteratorResult())
-            return false;
+        bool needsIteratorResult = funbox->needsIteratorResult();
+        if (needsIteratorResult) {
+            if (!emitPrepareIteratorResult())
+                return false;
+        }
 
         if (!emit1(JSOP_UNDEFINED))
             return false;
 
-        if (sc->asFunctionBox()->isStarGenerator() && !emitFinishIteratorResult(true))
-            return false;
+        if (needsIteratorResult) {
+            if (!emitFinishIteratorResult(true))
+                return false;
+        }
 
         if (!emit1(JSOP_SETRVAL))
             return false;
 
-        NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator);
-        if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
+        if (!emitGetDotGenerator())
             return false;
 
         // No need to check for finally blocks, etc as in EmitReturn.
         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
             return false;
     } else {
         // Non-generator functions just return |undefined|. The
         // JSOP_RETRVAL emitted below will do that, except if the
@@ -10353,25 +10381,30 @@ BytecodeEmitter::emitTree(ParseNode* pn,
         break;
 
       case PNK_RETURN:
         if (!emitReturn(pn))
             return false;
         break;
 
       case PNK_YIELD_STAR:
-        if (!emitYieldStar(pn->pn_left, pn->pn_right))
+        if (!emitYieldStar(pn->pn_kid))
             return false;
         break;
 
       case PNK_GENERATOR:
         if (!emit1(JSOP_GENERATOR))
             return false;
         break;
 
+      case PNK_INITIALYIELD:
+        if (!emitInitialYield(pn))
+            return false;
+        break;
+
       case PNK_YIELD:
       case PNK_AWAIT:
         if (!emitYield(pn))
             return false;
         break;
 
       case PNK_STATEMENTLIST:
         if (!emitStatementList(pn))
@@ -11040,17 +11073,17 @@ CGScopeNoteList::finish(ScopeNoteArray* 
             list[i].end += prologueLength;
         MOZ_ASSERT(list[i].end >= list[i].start);
         list[i].length = list[i].end - list[i].start;
         array->vector[i] = list[i];
     }
 }
 
 void
-CGYieldOffsetList::finish(YieldOffsetArray& array, uint32_t prologueLength)
+CGYieldAndAwaitOffsetList::finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength)
 {
     MOZ_ASSERT(length() == array.length());
 
     for (unsigned i = 0; i < length(); i++)
         array[i] = prologueLength + list[i];
 }
 
 /*
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -93,23 +93,23 @@ struct CGScopeNoteList {
 
     MOZ_MUST_USE bool append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
                              uint32_t parent);
     void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
     size_t length() const { return list.length(); }
     void finish(ScopeNoteArray* array, uint32_t prologueLength);
 };
 
-struct CGYieldOffsetList {
+struct CGYieldAndAwaitOffsetList {
     Vector<uint32_t> list;
-    explicit CGYieldOffsetList(JSContext* cx) : list(cx) {}
+    explicit CGYieldAndAwaitOffsetList(JSContext* cx) : list(cx) {}
 
     MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
     size_t length() const { return list.length(); }
-    void finish(YieldOffsetArray& array, uint32_t prologueLength);
+    void finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength);
 };
 
 // Use zero inline elements because these go on the stack and affect how many
 // nested functions are possible.
 typedef Vector<jsbytecode, 0> BytecodeVector;
 typedef Vector<jssrcnote, 0> SrcNotesVector;
 
 // Linked list of jump instructions that need to be patched. The linked list is
@@ -223,20 +223,20 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     CGConstList      constList;      /* constants to be included with the script */
     CGObjectList     objectList;     /* list of emitted objects */
     CGScopeList      scopeList;      /* list of emitted scopes */
     CGTryNoteList    tryNoteList;    /* list of emitted try notes */
     CGScopeNoteList  scopeNoteList;  /* list of emitted block scope notes */
 
     /*
-     * For each yield op, map the yield index (stored as bytecode operand) to
-     * the offset of the next op.
+     * For each yield or await op, map the yield and await index (stored as
+     * bytecode operand) to the offset of the next op.
      */
-    CGYieldOffsetList yieldOffsetList;
+    CGYieldAndAwaitOffsetList yieldAndAwaitOffsetList;
 
     uint16_t        typesetCount;   /* Number of JOF_TYPESET opcodes generated */
 
     bool            hasSingletons:1;    /* script contains singleton initializer JSOP_OBJECT */
 
     bool            hasTryFinally:1;    /* script contains finally block */
 
     bool            emittingRunOnceLambda:1; /* true while emitting a lambda which is only
@@ -593,19 +593,22 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
     MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
 
     MOZ_MUST_USE bool emitPrepareIteratorResult();
     MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
     MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
 
+    MOZ_MUST_USE bool emitGetDotGenerator();
+
+    MOZ_MUST_USE bool emitInitialYield(ParseNode* pn);
     MOZ_MUST_USE bool emitYield(ParseNode* pn);
     MOZ_MUST_USE bool emitYieldOp(JSOp op);
-    MOZ_MUST_USE bool emitYieldStar(ParseNode* iter, ParseNode* gen);
+    MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
 
     MOZ_MUST_USE bool emitPropLHS(ParseNode* pn);
     MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op);
     MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
 
     MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow);
     MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow);
 
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -113,19 +113,20 @@ ContainsHoistedDeclaration(JSContext* cx
       case PNK_THROW:
       case PNK_RETURN:
         MOZ_ASSERT(node->isArity(PN_UNARY));
         *result = false;
         return true;
 
       // These two aren't statements in the spec, but we sometimes insert them
       // in statement lists anyway.
+      case PNK_INITIALYIELD:
       case PNK_YIELD_STAR:
       case PNK_YIELD:
-        MOZ_ASSERT(node->isArity(PN_BINARY));
+        MOZ_ASSERT(node->isArity(PN_UNARY));
         *result = false;
         return true;
 
       // Other statements with no sub-statement components.
       case PNK_BREAK:
       case PNK_CONTINUE:
       case PNK_IMPORT:
       case PNK_IMPORT_SPEC_LIST:
@@ -1779,31 +1780,33 @@ Fold(JSContext* cx, ParseNode** pnp, Par
       case PNK_LET:
       case PNK_PARAMSBODY:
       case PNK_CALLSITEOBJ:
       case PNK_EXPORT_SPEC_LIST:
       case PNK_IMPORT_SPEC_LIST:
       case PNK_GENEXP:
         return FoldList(cx, pn, parser, inGenexpLambda);
 
+      case PNK_INITIALYIELD:
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
+        MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) &&
+                   pn->pn_kid->pn_left->isKind(PNK_NAME) &&
+                   pn->pn_kid->pn_right->isKind(PNK_GENERATOR));
+        return true;
+
       case PNK_YIELD_STAR:
-        MOZ_ASSERT(pn->isArity(PN_BINARY));
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME));
-        return Fold(cx, &pn->pn_left, parser, inGenexpLambda);
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
+        return Fold(cx, &pn->pn_kid, parser, inGenexpLambda);
 
       case PNK_YIELD:
       case PNK_AWAIT:
-        MOZ_ASSERT(pn->isArity(PN_BINARY));
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME) ||
-                   (pn->pn_right->isKind(PNK_ASSIGN) &&
-                    pn->pn_right->pn_left->isKind(PNK_NAME) &&
-                    pn->pn_right->pn_right->isKind(PNK_GENERATOR)));
-        if (!pn->pn_left)
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
+        if (!pn->pn_kid)
             return true;
-        return Fold(cx, &pn->pn_left, parser, inGenexpLambda);
+        return Fold(cx, &pn->pn_kid, parser, inGenexpLambda);
 
       case PNK_RETURN:
         return FoldReturn(cx, pn, parser, inGenexpLambda);
 
       case PNK_TRY:
         return FoldTry(cx, pn, parser, inGenexpLambda);
 
       case PNK_CATCH:
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -422,30 +422,34 @@ class FullParseHandler
 
         ParseNode* classMethod = new_<ClassMethod>(key, fn, op, isStatic);
         if (!classMethod)
             return false;
         methodList->append(classMethod);
         return true;
     }
 
-    ParseNode* newYieldExpression(uint32_t begin, ParseNode* value, ParseNode* gen,
-                                  JSOp op = JSOP_YIELD) {
-        TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
-        return new_<BinaryNode>(PNK_YIELD, op, pos, value, gen);
+    ParseNode* newInitialYieldExpression(uint32_t begin, ParseNode* gen) {
+        TokenPos pos(begin, begin + 1);
+        return new_<UnaryNode>(PNK_INITIALYIELD, JSOP_INITIALYIELD, pos, gen);
     }
 
-    ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value, ParseNode* gen) {
-        TokenPos pos(begin, value->pn_pos.end);
-        return new_<BinaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value, gen);
+    ParseNode* newYieldExpression(uint32_t begin, ParseNode* value) {
+        TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
+        return new_<UnaryNode>(PNK_YIELD, JSOP_YIELD, pos, value);
     }
 
-    ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value, ParseNode* gen) {
+    ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value) {
+        TokenPos pos(begin, value->pn_pos.end);
+        return new_<UnaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value);
+    }
+
+    ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value) {
         TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
-        return new_<BinaryNode>(PNK_AWAIT, JSOP_YIELD, pos, value, gen);
+        return new_<UnaryNode>(PNK_AWAIT, JSOP_AWAIT, pos, value);
     }
 
     // Statements
 
     ParseNode* newStatementList(const TokenPos& pos) {
         return new_<ListNode>(PNK_STATEMENTLIST, pos);
     }
 
@@ -488,18 +492,17 @@ class FullParseHandler
             return false;
 
         MOZ_ASSERT(genName->getOp() == JSOP_GETNAME);
         genName->setOp(JSOP_SETNAME);
         ParseNode* genInit = newBinary(PNK_ASSIGN, genName, makeGen);
         if (!genInit)
             return false;
 
-        ParseNode* initialYield = newYieldExpression(yieldPos.begin, nullptr, genInit,
-                                                     JSOP_INITIALYIELD);
+        ParseNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit);
         if (!initialYield)
             return false;
 
         stmtList->prepend(initialYield);
         return true;
     }
 
     ParseNode* newSetThis(ParseNode* thisName, ParseNode* val) {
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -496,34 +496,35 @@ class NameResolver
             if (ParseNode* caseExpr = cur->pn_left) {
                 if (!resolve(caseExpr, prefix))
                     return false;
             }
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
+          case PNK_INITIALYIELD:
+            MOZ_ASSERT(cur->pn_kid->isKind(PNK_ASSIGN) &&
+                       cur->pn_kid->pn_left->isKind(PNK_NAME) &&
+                       cur->pn_kid->pn_right->isKind(PNK_GENERATOR));
+            break;
+
           case PNK_YIELD_STAR:
-            MOZ_ASSERT(cur->isArity(PN_BINARY));
-            MOZ_ASSERT(cur->pn_right->isKind(PNK_NAME));
-            if (!resolve(cur->pn_left, prefix))
+            MOZ_ASSERT(cur->isArity(PN_UNARY));
+            if (!resolve(cur->pn_kid, prefix))
                 return false;
             break;
 
           case PNK_YIELD:
           case PNK_AWAIT:
-            MOZ_ASSERT(cur->isArity(PN_BINARY));
-            if (cur->pn_left) {
-                if (!resolve(cur->pn_left, prefix))
+            MOZ_ASSERT(cur->isArity(PN_UNARY));
+            if (cur->pn_kid) {
+                if (!resolve(cur->pn_kid, prefix))
                     return false;
             }
-            MOZ_ASSERT(cur->pn_right->isKind(PNK_NAME) ||
-                       (cur->pn_right->isKind(PNK_ASSIGN) &&
-                        cur->pn_right->pn_left->isKind(PNK_NAME) &&
-                        cur->pn_right->pn_right->isKind(PNK_GENERATOR)));
             break;
 
           case PNK_RETURN:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (ParseNode* returnValue = cur->pn_kid) {
                 if (!resolve(returnValue, prefix))
                     return false;
             }
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -281,32 +281,34 @@ PushNodeChildren(ParseNode* pn, NodeStac
       case PNK_CLASSNAMES: {
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         if (pn->pn_left)
             stack->push(pn->pn_left);
         stack->push(pn->pn_right);
         return PushResult::Recyclable;
       }
 
-      // The left half is the expression being yielded.  The right half is
-      // internal goop: a name reference to the invisible '.generator' local
-      // variable, or an assignment of a PNK_GENERATOR node to the '.generator'
-      // local, for a synthesized, prepended initial yield.  Yum!
+      // The child is an assignment of a PNK_GENERATOR node to the
+      // '.generator' local, for a synthesized, prepended initial yield.
+      case PNK_INITIALYIELD: {
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
+        MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) &&
+                   pn->pn_kid->pn_left->isKind(PNK_NAME) &&
+                   pn->pn_kid->pn_right->isKind(PNK_GENERATOR));
+        stack->push(pn->pn_kid);
+        return PushResult::Recyclable;
+      }
+
+      // The child is the expression being yielded.
       case PNK_YIELD_STAR:
       case PNK_YIELD:
       case PNK_AWAIT: {
-        MOZ_ASSERT(pn->isArity(PN_BINARY));
-        MOZ_ASSERT(pn->pn_right);
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME) ||
-                   (pn->pn_right->isKind(PNK_ASSIGN) &&
-                    pn->pn_right->pn_left->isKind(PNK_NAME) &&
-                    pn->pn_right->pn_right->isKind(PNK_GENERATOR)));
-        if (pn->pn_left)
-            stack->push(pn->pn_left);
-        stack->push(pn->pn_right);
+        MOZ_ASSERT(pn->isArity(PN_UNARY));
+        if (pn->pn_kid)
+            stack->push(pn->pn_kid);
         return PushResult::Recyclable;
       }
 
       // A return node's child is what you'd expect: the return expression,
       // if any.
       case PNK_RETURN: {
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (pn->pn_kid)
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -78,16 +78,17 @@ class ObjectBox;
     F(DELETEELEM) \
     F(DELETEEXPR) \
     F(TRY) \
     F(CATCH) \
     F(CATCHLIST) \
     F(THROW) \
     F(DEBUGGER) \
     F(GENERATOR) \
+    F(INITIALYIELD) \
     F(YIELD) \
     F(YIELD_STAR) \
     F(GENEXP) \
     F(ARRAYCOMP) \
     F(ARRAYPUSH) \
     F(LEXICALSCOPE) \
     F(LET) \
     F(IMPORT) \
@@ -412,18 +413,19 @@ IsTypeofKind(ParseNodeKind kind)
  * PNK_THIS,        unary   pn_kid: '.this' Name if function `this`, else nullptr
  * PNK_SUPERBASE    unary   pn_kid: '.this' Name
  *
  * PNK_SETTHIS      binary  pn_left: '.this' Name, pn_right: SuperCall
  *
  * PNK_LEXICALSCOPE scope   pn_u.scope.bindings: scope bindings
  *                          pn_u.scope.body: scope body
  * PNK_GENERATOR    nullary
- * PNK_YIELD,       binary  pn_left: expr or null
- * PNK_YIELD_STAR,          pn_right: generator object
+ * PNK_INITIALYIELD unary   pn_kid: generator object
+ * PNK_YIELD,       unary   pn_kid: expr or null
+ * PNK_YIELD_STAR,
  * PNK_AWAIT
  * PNK_ARRAYCOMP    list    pn_count: 1
  *                          pn_head: list of 1 element, which is block
  *                          enclosing for loop(s) and optionally
  *                          if-guarded PNK_ARRAYPUSH
  * PNK_ARRAYPUSH    unary   pn_op: JSOP_ARRAYCOMP
  *                          pn_kid: array comprehension expression
  * PNK_NOP          nullary
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2414,20 +2414,18 @@ Parser<SyntaxParseHandler>::finishFuncti
     // parse.
     PropagateTransitiveParseFlags(funbox, lazy);
 
     fun->initLazyScript(lazy);
     return true;
 }
 
 static YieldHandling
-GetYieldHandling(GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
-{
-    if (asyncKind == AsyncFunction)
-        return YieldIsName;
+GetYieldHandling(GeneratorKind generatorKind)
+{
     if (generatorKind == NotGenerator)
         return YieldIsName;
     return YieldIsKeyword;
 }
 
 template <>
 ParseNode*
 Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
@@ -2455,17 +2453,17 @@ Parser<FullParseHandler>::standaloneFunc
         return null();
     funbox->initStandaloneFunction(enclosingScope);
 
     ParseContext funpc(this, funbox, newDirectives);
     if (!funpc.init())
         return null();
     funpc.setIsStandaloneFunctionBody();
 
-    YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    YieldHandling yieldHandling = GetYieldHandling(generatorKind);
     AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
     if (!functionFormalParametersAndBody(InAllowed, yieldHandling, fn, Statement,
                                          parameterListEnd, /* isStandaloneFunction = */ true))
     {
         return null();
     }
 
     TokenKind tt;
@@ -2614,38 +2612,38 @@ Parser<ParseHandler>::functionBody(InHan
         if (pc->isAsync()) {
             handler.addStatementToList(stmtList, pn);
             pn = stmtList;
         }
     }
 
     switch (pc->generatorKind()) {
       case NotGenerator:
-        MOZ_ASSERT(pc->lastYieldOffset == startYieldOffset);
+        MOZ_ASSERT_IF(!pc->isAsync(), pc->lastYieldOffset == startYieldOffset);
         break;
 
       case LegacyGenerator:
         MOZ_ASSERT(pc->lastYieldOffset != startYieldOffset);
 
         // These should throw while parsing the yield expression.
         MOZ_ASSERT(kind != Arrow);
         MOZ_ASSERT(!IsGetterKind(kind));
         MOZ_ASSERT(!IsSetterKind(kind));
         MOZ_ASSERT(!IsConstructorKind(kind));
         MOZ_ASSERT(kind != Method);
         MOZ_ASSERT(type != ExpressionBody);
         break;
 
       case StarGenerator:
-        MOZ_ASSERT_IF(!pc->isAsync(), kind != Arrow);
-        MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
+        MOZ_ASSERT(kind != Arrow);
+        MOZ_ASSERT(type == StatementListBody);
         break;
     }
 
-    if (pc->isGenerator()) {
+    if (pc->needsDotGeneratorName()) {
         MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
         if (!declareDotGeneratorName())
             return null();
         Node generator = newDotGeneratorName();
         if (!generator)
             return null();
         if (!handler.prependInitialYield(pn, generator))
             return null();
@@ -2676,29 +2674,29 @@ Parser<ParseHandler>::newFunction(Handle
 
     gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
     JSFunction::Flags flags;
 #ifdef DEBUG
     bool isGlobalSelfHostedBuiltin = false;
 #endif
     switch (kind) {
       case Expression:
-        flags = (generatorKind == NotGenerator
+        flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
                  ? JSFunction::INTERPRETED_LAMBDA
-                 : JSFunction::INTERPRETED_LAMBDA_GENERATOR);
+                 : JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
         break;
       case Arrow:
         flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case Method:
         MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
-        flags = (generatorKind == NotGenerator
+        flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
                  ? JSFunction::INTERPRETED_METHOD
-                 : JSFunction::INTERPRETED_METHOD_GENERATOR);
+                 : JSFunction::INTERPRETED_METHOD_GENERATOR_OR_ASYNC);
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case ClassConstructor:
       case DerivedClassConstructor:
         flags = JSFunction::INTERPRETED_CLASS_CONSTRUCTOR;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case Getter:
@@ -2714,19 +2712,19 @@ Parser<ParseHandler>::newFunction(Handle
       default:
         MOZ_ASSERT(kind == Statement);
 #ifdef DEBUG
         if (options().selfHostingMode && !pc->isFunctionBox()) {
             isGlobalSelfHostedBuiltin = true;
             allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         }
 #endif
-        flags = (generatorKind == NotGenerator
+        flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
                  ? JSFunction::INTERPRETED_NORMAL
-                 : JSFunction::INTERPRETED_GENERATOR);
+                 : JSFunction::INTERPRETED_GENERATOR_OR_ASYNC);
     }
 
     // We store the async wrapper in a slot for later access.
     if (asyncKind == AsyncFunction)
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
 
     fun = NewFunctionWithProto(context, nullptr, 0, flags, nullptr, atom, proto,
                                allocKind, TenuredObject);
@@ -3239,29 +3237,28 @@ template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionDefinition(Node pn, InHandling inHandling,
                                          YieldHandling yieldHandling, HandleAtom funName,
                                          FunctionSyntaxKind kind,
                                          GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
                                          bool tryAnnexB /* = false */)
 {
     MOZ_ASSERT_IF(kind == Statement, funName);
-    MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator);
 
     // When fully parsing a LazyScript, we do not fully reparse its inner
     // functions, which are also lazy. Instead, their free variables and
     // source extents are recorded and may be skipped.
     if (handler.canSkipLazyInnerFunctions()) {
         if (!skipLazyInnerFunction(pn, kind, tryAnnexB))
             return null();
         return pn;
     }
 
     RootedObject proto(context);
-    if (generatorKind == StarGenerator) {
+    if (generatorKind == StarGenerator || asyncKind == AsyncFunction) {
         // If we are off thread, the generator meta-objects have
         // already been created by js::StartOffThreadParseTask, so cx will not
         // be necessary.
         JSContext* cx = context->helperThread() ? nullptr : context;
         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
         if (!proto)
             return null();
     }
@@ -3321,17 +3318,17 @@ Parser<FullParseHandler>::trySyntaxParse
                                                       Directives* newDirectives)
 {
     // Try a syntax parse for this inner function.
     do {
         // If we're assuming this function is an IIFE, always perform a full
         // parse to avoid the overhead of a lazy syntax-only parse. Although
         // the prediction may be incorrect, IIFEs are common enough that it
         // pays off for lots of code.
-        if (pn->isLikelyIIFE() && generatorKind == NotGenerator)
+        if (pn->isLikelyIIFE() && generatorKind == NotGenerator && asyncKind == SyncFunction)
             break;
 
         Parser<SyntaxParseHandler>* parser = handler.syntaxParser;
         if (!parser)
             break;
 
         UsedNameTracker::RewindToken token = usedNames.getRewindToken();
 
@@ -3493,17 +3490,17 @@ Parser<FullParseHandler>::standaloneLazy
     // is a not-async arrow, use TokenStream::Operand to keep
     // verifyConsistentModifier from complaining (we will use
     // TokenStream::Operand in functionArguments).
     TokenStream::Modifier modifier = (fun->isArrow() && asyncKind == SyncFunction)
                                      ? TokenStream::Operand : TokenStream::None;
     if (!tokenStream.peekTokenPos(&pn->pn_pos, modifier))
         return null();
 
-    YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    YieldHandling yieldHandling = GetYieldHandling(generatorKind);
     FunctionSyntaxKind syntaxKind = Statement;
     if (fun->isClassConstructor())
         syntaxKind = ClassConstructor;
     else if (fun->isMethod())
         syntaxKind = Method;
     else if (fun->isGetter())
         syntaxKind = Getter;
     else if (fun->isSetter())
@@ -3568,17 +3565,17 @@ Parser<ParseHandler>::functionFormalPara
     }
 
     // Parse the function body.
     FunctionBodyType bodyType = StatementListBody;
     TokenKind tt;
     if (!tokenStream.getToken(&tt, TokenStream::Operand))
         return false;
     if (tt != TOK_LC) {
-        if ((funbox->isStarGenerator() && !funbox->isAsync()) || kind == Method ||
+        if (funbox->isStarGenerator() || kind == Method ||
             kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure ||
             IsConstructorKind(kind)) {
             error(JSMSG_CURLY_BEFORE_BODY);
             return false;
         }
 
         if (kind != Arrow) {
 #if JS_HAS_EXPR_CLOSURES
@@ -3596,17 +3593,17 @@ Parser<ParseHandler>::functionFormalPara
         funbox->setIsExprBody();
     }
 
     // Arrow function parameters inherit yieldHandling from the enclosing
     // context, but the arrow body doesn't. E.g. in |(a = yield) => yield|,
     // |yield| in the parameters is either a name or keyword, depending on
     // whether the arrow function is enclosed in a generator function or not.
     // Whereas the |yield| in the function body is always parsed as a name.
-    YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind(), pc->asyncKind());
+    YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
     Node body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
     if (!body)
         return false;
 
     if ((kind != Method && !IsConstructorKind(kind)) && fun->explicitName()) {
         RootedPropertyName propertyName(context, fun->explicitName()->asPropertyName());
         // `await` cannot be checked at this point because of different context.
         // It should already be checked before this point.
@@ -3688,17 +3685,17 @@ Parser<ParseHandler>::functionStmt(Yield
             return null();
         }
     }
 
     TokenKind tt;
     if (!tokenStream.getToken(&tt))
         return null();
 
-    GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator;
+    GeneratorKind generatorKind = NotGenerator;
     if (tt == TOK_MUL) {
         if (asyncKind != SyncFunction) {
             error(JSMSG_ASYNC_GENERATOR);
             return null();
         }
         generatorKind = StarGenerator;
         if (!tokenStream.getToken(&tt))
             return null();
@@ -3719,17 +3716,17 @@ Parser<ParseHandler>::functionStmt(Yield
     }
 
     // Note the declared name and check for early errors.
     bool tryAnnexB = false;
     if (declaredInStmt) {
         MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
         MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
 
-        if (!pc->sc()->strict() && generatorKind == NotGenerator) {
+        if (!pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction) {
             // Under sloppy mode, try Annex B.3.3 semantics. If making an
             // additional 'var' binding of the same name does not throw an
             // early error, do so. This 'var' binding would be assigned
             // the function object when its declaration is reached, not at
             // the start of the block.
             if (!tryDeclareVarForAnnexBLexicalFunction(name, pos().begin, &tryAnnexB))
                 return null();
         }
@@ -3743,44 +3740,44 @@ Parser<ParseHandler>::functionStmt(Yield
         if (!noteDeclaredName(name, kind, pos()))
             return null();
     }
 
     Node pn = handler.newFunctionStatement();
     if (!pn)
         return null();
 
-    YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    YieldHandling newYieldHandling = GetYieldHandling(generatorKind);
     return functionDefinition(pn, InAllowed, newYieldHandling, name, Statement, generatorKind,
                               asyncKind, tryAnnexB);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind asyncKind)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
 
     AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
-    GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator;
+    GeneratorKind generatorKind = NotGenerator;
     TokenKind tt;
     if (!tokenStream.getToken(&tt))
         return null();
 
     if (tt == TOK_MUL) {
         if (asyncKind != SyncFunction) {
             error(JSMSG_ASYNC_GENERATOR);
             return null();
         }
         generatorKind = StarGenerator;
         if (!tokenStream.getToken(&tt))
             return null();
     }
 
-    YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    YieldHandling yieldHandling = GetYieldHandling(generatorKind);
 
     RootedPropertyName name(context);
     if (TokenKindIsPossibleIdentifier(tt)) {
         name = bindingIdentifier(yieldHandling);
         if (!name)
             return null();
     } else {
         tokenStream.ungetToken();
@@ -6369,39 +6366,16 @@ Parser<ParseHandler>::returnStatement(Yi
         return null();
     }
 
     return pn;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
-Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::Node expr,
-                                         bool isYieldStar)
-{
-    Node generator = newDotGeneratorName();
-    if (!generator)
-        return null();
-    if (isYieldStar)
-        return handler.newYieldStarExpression(begin, expr, generator);
-    return handler.newYieldExpression(begin, expr, generator);
-}
-
-template <typename ParseHandler>
-typename ParseHandler::Node
-Parser<ParseHandler>::newAwaitExpression(uint32_t begin, typename ParseHandler::Node expr)
-{
-    Node generator = newDotGeneratorName();
-    if (!generator)
-        return null();
-    return handler.newAwaitExpression(begin, expr, generator);
-}
-
-template <typename ParseHandler>
-typename ParseHandler::Node
 Parser<ParseHandler>::yieldExpression(InHandling inHandling)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD));
     uint32_t begin = pos().begin;
 
     switch (pc->generatorKind()) {
       case StarGenerator:
       {
@@ -6438,17 +6412,19 @@ Parser<ParseHandler>::yieldExpression(In
             kind = PNK_YIELD_STAR;
             tokenStream.consumeKnownToken(TOK_MUL, TokenStream::Operand);
             MOZ_FALLTHROUGH;
           default:
             exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
             if (!exprNode)
                 return null();
         }
-        return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR);
+        if (kind == PNK_YIELD_STAR)
+            return handler.newYieldStarExpression(begin, exprNode);
+        return handler.newYieldExpression(begin, exprNode);
       }
 
       case NotGenerator:
         // We are in code that has not seen a yield, but we are in JS 1.7 or
         // later.  Try to transition to being a legacy generator.
         MOZ_ASSERT(tokenStream.versionNumber() >= JSVERSION_1_7);
         MOZ_ASSERT(pc->lastYieldOffset == ParseContext::NoYieldOffset);
 
@@ -6516,17 +6492,17 @@ Parser<ParseHandler>::yieldExpression(In
             tokenStream.addModifierException(TokenStream::NoneIsOperand);
             break;
           default:
             exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
             if (!exprNode)
                 return null();
         }
 
-        return newYieldExpression(begin, exprNode);
+        return handler.newYieldExpression(begin, exprNode);
       }
     }
 
     MOZ_CRASH("yieldExpr");
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
@@ -7996,40 +7972,38 @@ Parser<ParseHandler>::assignExpr(InHandl
         if (next == TOK_LC)
             isBlock = true;
 
         tokenStream.seek(start);
 
         if (!tokenStream.peekToken(&next, TokenStream::Operand))
             return null();
 
-        GeneratorKind generatorKind = NotGenerator;
         FunctionAsyncKind asyncKind = SyncFunction;
 
         if (next == TOK_ASYNC) {
             tokenStream.consumeKnownToken(next, TokenStream::Operand);
 
             TokenKind nextSameLine = TOK_EOF;
             if (!tokenStream.peekTokenSameLine(&nextSameLine))
                 return null();
 
             if (nextSameLine == TOK_ARROW) {
                 tokenStream.ungetToken();
             } else {
-                generatorKind = StarGenerator;
                 asyncKind = AsyncFunction;
             }
         }
 
         Node pn = handler.newArrowFunction();
         if (!pn)
             return null();
 
         Node arrowFunc = functionDefinition(pn, inHandling, yieldHandling, nullptr,
-                                            Arrow, generatorKind, asyncKind);
+                                            Arrow, NotGenerator, asyncKind);
         if (!arrowFunc)
             return null();
 
         if (isBlock) {
             // This arrow function could be a non-trailing member of a comma
             // expression or a semicolon terminating a full expression.  If so,
             // the next token is that comma/semicolon, gotten with None:
             //
@@ -8265,17 +8239,17 @@ Parser<ParseHandler>::unaryExpr(YieldHan
       }
 
       case TOK_AWAIT: {
         if (pc->isAsync()) {
             Node kid = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
             if (!kid)
                 return null();
             pc->lastAwaitOffset = begin;
-            return newAwaitExpression(begin, kid);
+            return handler.newAwaitExpression(begin, kid);
         }
       }
 
         MOZ_FALLTHROUGH;
 
       default: {
         Node expr = memberExpr(yieldHandling, tripledotHandling, tt, /* allowCallSyntax = */ true,
                                possibleError, invoked);
@@ -8522,17 +8496,17 @@ Parser<ParseHandler>::comprehensionTail(
     Node bodyExpr = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
     if (!bodyExpr)
         return null();
 
     if (comprehensionKind == NotGenerator)
         return handler.newArrayPush(begin, bodyExpr);
 
     MOZ_ASSERT(comprehensionKind == StarGenerator);
-    Node yieldExpr = newYieldExpression(begin, bodyExpr);
+    Node yieldExpr = handler.newYieldExpression(begin, bodyExpr);
     if (!yieldExpr)
         return null();
     yieldExpr = handler.parenthesize(yieldExpr);
 
     return handler.newExprStatement(yieldExpr, pos().end);
 }
 
 // Parse an ES6-era generator or array comprehension, starting at the first
@@ -9626,26 +9600,25 @@ Parser<ParseHandler>::methodDefinition(P
       case PropertyType::DerivedConstructor:
         kind = DerivedClassConstructor;
         break;
 
       default:
         MOZ_CRASH("unexpected property type");
     }
 
-    GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod ||
-                                   propType == PropertyType::AsyncMethod)
+    GeneratorKind generatorKind = propType == PropertyType::GeneratorMethod
                                   ? StarGenerator
                                   : NotGenerator;
 
     FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod)
                                   ? AsyncFunction
                                   : SyncFunction;
 
-    YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    YieldHandling yieldHandling = GetYieldHandling(generatorKind);
 
     Node pn = handler.newFunctionExpression();
     if (!pn)
         return null();
 
     return functionDefinition(pn, InAllowed, yieldHandling, funName, kind, generatorKind, asyncKind);
 }
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -496,32 +496,32 @@ class ParseContext : public Nestable<Par
 
     // Most functions start off being parsed as non-generators.
     // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7.
     // An ES6 generator is marked as a "star generator" before its body is parsed.
     GeneratorKind generatorKind() const {
         return sc_->isFunctionBox() ? sc_->asFunctionBox()->generatorKind() : NotGenerator;
     }
 
-    bool isGenerator() const {
-        return generatorKind() != NotGenerator;
-    }
-
     bool isLegacyGenerator() const {
         return generatorKind() == LegacyGenerator;
     }
 
     bool isStarGenerator() const {
         return generatorKind() == StarGenerator;
     }
 
     bool isAsync() const {
         return sc_->isFunctionBox() && sc_->asFunctionBox()->isAsync();
     }
 
+    bool needsDotGeneratorName() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+
     FunctionAsyncKind asyncKind() const {
         return isAsync() ? AsyncFunction : SyncFunction;
     }
 
     bool isArrowFunction() const {
         return sc_->isFunctionBox() && sc_->asFunctionBox()->function()->isArrow();
     }
 
@@ -811,17 +811,19 @@ class ParserBase : public StrictModeGett
     const char* getFilename() const { return tokenStream.getFilename(); }
     JSVersion versionNumber() const { return tokenStream.versionNumber(); }
     TokenPos pos() const { return tokenStream.currentToken().pos; }
 
     // Determine whether |yield| is a valid name in the current context, or
     // whether it's prohibited due to strictness, JS version, or occurrence
     // inside a star generator.
     bool yieldExpressionsSupported() {
-        return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync();
+        return (versionNumber() >= JSVERSION_1_7 && !pc->isAsync()) ||
+               pc->isStarGenerator() ||
+               pc->isLegacyGenerator();
     }
 
     virtual bool strictMode() { return pc->sc()->strict(); }
     bool setLocalStrictMode(bool strict) {
         MOZ_ASSERT(tokenStream.debugHasNoLookahead());
         return pc->sc()->setLocalStrictMode(strict);
     }
 
@@ -1081,18 +1083,16 @@ class Parser final : public ParserBase, 
     bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
     bool appendToCallSiteObj(Node callSiteObj);
     bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
                                         TokenKind* ttp);
     bool checkStatementsEOF();
 
     inline Node newName(PropertyName* name);
     inline Node newName(PropertyName* name, TokenPos pos);
-    inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false);
-    inline Node newAwaitExpression(uint32_t begin, Node expr);
 
     inline bool abortIfSyntaxParser();
 
   public:
     /* Public entry points for parsing. */
     Node statement(YieldHandling yieldHandling);
     Node statementListItem(YieldHandling yieldHandling, bool canHaveDirectives = false);
 
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -512,39 +512,51 @@ class FunctionBox : public ObjectBox, pu
                       enclosingScope_ == function()->lazyScript()->enclosingScope());
         return enclosingScope_;
     }
 
     bool needsCallObjectRegardlessOfBindings() const {
         return hasExtensibleScope() ||
                needsHomeObject() ||
                isDerivedClassConstructor() ||
-               isGenerator();
+               isStarGenerator() ||
+               isLegacyGenerator() ||
+               isAsync();
     }
 
     bool hasExtraBodyVarScope() const {
         return hasParameterExprs &&
                (extraVarScopeBindings_ ||
                 needsExtraBodyVarEnvironmentRegardlessOfBindings());
     }
 
     bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
         MOZ_ASSERT(hasParameterExprs);
-        return hasExtensibleScope() || isGenerator();
+        return hasExtensibleScope() || needsDotGeneratorName();
     }
 
     bool isLikelyConstructorWrapper() const {
         return usesArguments && usesApply && usesThis && !usesReturn;
     }
 
     GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
     FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
+
+    bool needsFinalYield() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+    bool needsDotGeneratorName() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+    bool needsIteratorResult() const {
+        return isStarGenerator() || isAsync();
+    }
+
     bool isAsync() const { return asyncKind() == AsyncFunction; }
     bool isArrow() const { return function()->isArrow(); }
 
     bool hasRest() const { return hasRest_; }
     void setHasRest() {
         hasRest_ = true;
     }
 
@@ -552,17 +564,17 @@ class FunctionBox : public ObjectBox, pu
     void setIsExprBody() {
         isExprBody_ = true;
     }
 
     void setGeneratorKind(GeneratorKind kind) {
         // A generator kind can be set at initialization, or when "yield" is
         // first seen.  In both cases the transition can only happen from
         // NotGenerator.
-        MOZ_ASSERT(!isGenerator());
+        MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
         generatorKindBits_ = GeneratorKindAsBits(kind);
     }
 
     bool hasExtensibleScope()        const { return funCxFlags.hasExtensibleScope; }
     bool hasThisBinding()            const { return funCxFlags.hasThisBinding; }
     bool argumentsHasLocalBinding()  const { return funCxFlags.argumentsHasLocalBinding; }
     bool definitelyNeedsArgsObj()    const { return funCxFlags.definitelyNeedsArgsObj; }
     bool needsHomeObject()           const { return funCxFlags.needsHomeObject; }
@@ -639,15 +651,19 @@ SharedContext::asModuleContext()
 // the heap.  This way there is less information to copy off the stack when
 // suspending, and back on when resuming.  It also avoids the need to create
 // and invalidate DebugScope proxies for unaliased locals in a generator
 // frame, as the generator frame will be copied out to the heap and released
 // only by GC.
 inline bool
 SharedContext::allBindingsClosedOver()
 {
-    return bindingsAccessedDynamically() || (isFunctionBox() && asFunctionBox()->isGenerator());
+    return bindingsAccessedDynamically() ||
+           (isFunctionBox() &&
+            (asFunctionBox()->isStarGenerator() ||
+             asFunctionBox()->isLegacyGenerator() ||
+             asFunctionBox()->isAsync()));
 }
 
 } // namespace frontend
 } // namespace js
 
 #endif /* frontend_SharedContext_h */
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -295,19 +295,19 @@ class SyntaxParseHandler
     Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
     Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
 
     MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
     MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
     MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
     MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
     MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
-    Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
-    Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
-    Node newAwaitExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
+    Node newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; }
+    Node newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; }
+    Node newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; }
 
     // Statements
 
     Node newStatementList(const TokenPos& pos) { return NodeGeneric; }
     void addStatementToList(Node list, Node stmt) {}
     void addCaseStatementToList(Node list, Node stmt) {}
     MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
     Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/for-of-iterator-close-debugger.js
@@ -0,0 +1,15 @@
+// |jit-test| error:ReferenceError
+
+// for-of should close iterator even if the exception is once caught by the
+// debugger.
+
+var g = newGlobal();
+g.parent = this;
+g.eval("new Debugger(parent).onExceptionUnwind = function () { };");
+// jsfunfuzz-generated
+for (var x of []) {};
+for (var l of [0]) {
+    for (var y = 0; y < 1; y++) {
+        g2;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1341321.js
@@ -0,0 +1,20 @@
+if (helperThreadCount() == 0)
+    quit();
+
+// The new Debugger here should throw but we don't have a way to verify this
+// (exceptions that worker threads throw do not cause the test to fail).
+evalInCooperativeThread('cooperativeYield(); var dbg = new Debugger();');
+
+var dbg = new Debugger;
+assertEq(dbg.addAllGlobalsAsDebuggees(), undefined);
+
+function assertThrows(f) {
+    var exception = false;
+    try { f(); } catch (e) { exception = true; }
+    assertEq(exception, true);
+}
+
+var dbg = new Debugger;
+dbg.onNewGlobalObject = function(global) {};
+assertThrows(() => evalInCooperativeThread("var x = 3"));
+assertThrows(cooperativeYield);
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -506,19 +506,20 @@ HasLiveStackValueAtDepth(JSScript* scrip
         switch (tn->kind) {
           case JSTRY_FOR_IN:
             // For-in loops have only the iterator on stack.
             if (stackDepth == tn->stackDepth)
                 return true;
             break;
 
           case JSTRY_FOR_OF:
-            // For-of loops have both the iterator and the result object on
-            // stack. The iterator is below the result object.
-            if (stackDepth == tn->stackDepth - 1)
+            // For-of loops have the iterator, the result object, and the value
+            // of the result object on stack. The iterator is below the result
+            // object and the value.
+            if (stackDepth == tn->stackDepth - 2)
                 return true;
             break;
 
           case JSTRY_DESTRUCTURING_ITERCLOSE:
             // Destructuring code that need to call IteratorClose have both
             // the iterator and the "done" value on the stack.
             if (stackDepth == tn->stackDepth || stackDepth == tn->stackDepth - 1)
                 return true;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -39,17 +39,17 @@
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::AssertedCast;
 
 BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script)
   : BaselineCompilerSpecific(cx, alloc, script),
-    yieldOffsets_(cx),
+    yieldAndAwaitOffsets_(cx),
     modifiesArguments_(false)
 {
 }
 
 bool
 BaselineCompiler::init()
 {
     if (!analysis_.init(alloc_, cx->caches().gsnCache))
@@ -206,17 +206,17 @@ BaselineCompiler::compile()
                             epilogueOffset_.offset(),
                             profilerEnterFrameToggleOffset_.offset(),
                             profilerExitFrameToggleOffset_.offset(),
                             postDebugPrologueOffset_.offset(),
                             icEntries_.length(),
                             pcMappingIndexEntries.length(),
                             pcEntries.length(),
                             bytecodeTypeMapEntries,
-                            yieldOffsets_.length(),
+                            yieldAndAwaitOffsets_.length(),
                             traceLoggerToggleOffsets_.length()),
         JS::DeletePolicy<BaselineScript>(cx->runtime()));
     if (!baselineScript) {
         ReportOutOfMemory(cx);
         return Method_Error;
     }
 
     baselineScript->setMethod(code);
@@ -267,17 +267,17 @@ BaselineCompiler::compile()
 
     uint32_t* bytecodeMap = baselineScript->bytecodeTypeMap();
     FillBytecodeTypeMap(script, bytecodeMap);
 
     // The last entry in the last index found, and is used to avoid binary
     // searches for the sought entry when queries are in linear order.
     bytecodeMap[script->nTypeSets()] = 0;
 
-    baselineScript->copyYieldEntries(script, yieldOffsets_);
+    baselineScript->copyYieldAndAwaitEntries(script, yieldAndAwaitOffsets_);
 
     if (compileDebugInstrumentation_)
         baselineScript->setHasDebugInstrumentation();
 
     // Always register a native => bytecode mapping entry, since profiler can be
     // turned on with baseline jitcode on stack, and baseline jitcode cannot be invalidated.
     {
         JitSpew(JitSpew_Profiling, "Added JitcodeGlobalEntry for baseline script %s:%" PRIuSIZE " (%p)",
@@ -4173,47 +4173,49 @@ BaselineCompiler::emit_JSOP_GENERATOR()
         return false;
 
     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
     frame.push(R0);
     return true;
 }
 
 bool
-BaselineCompiler::addYieldOffset()
-{
-    MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD);
-
-    uint32_t yieldIndex = GET_UINT24(pc);
-
-    while (yieldIndex >= yieldOffsets_.length()) {
-        if (!yieldOffsets_.append(0))
+BaselineCompiler::addYieldAndAwaitOffset()
+{
+    MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD || *pc == JSOP_AWAIT);
+
+    uint32_t yieldAndAwaitIndex = GET_UINT24(pc);
+
+    while (yieldAndAwaitIndex >= yieldAndAwaitOffsets_.length()) {
+        if (!yieldAndAwaitOffsets_.append(0))
             return false;
     }
 
-    static_assert(JSOP_INITIALYIELD_LENGTH == JSOP_YIELD_LENGTH,
-                  "code below assumes INITIALYIELD and YIELD have same length");
-    yieldOffsets_[yieldIndex] = script->pcToOffset(pc + JSOP_YIELD_LENGTH);
+    static_assert(JSOP_INITIALYIELD_LENGTH == JSOP_YIELD_LENGTH &&
+                  JSOP_INITIALYIELD_LENGTH == JSOP_AWAIT_LENGTH,
+                  "code below assumes INITIALYIELD and YIELD and AWAIT have same length");
+    yieldAndAwaitOffsets_[yieldAndAwaitIndex] = script->pcToOffset(pc + JSOP_YIELD_LENGTH);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_INITIALYIELD()
 {
-    if (!addYieldOffset())
+    if (!addYieldAndAwaitOffset())
         return false;
 
     frame.syncStack(0);
     MOZ_ASSERT(frame.stackDepth() == 1);
 
     Register genObj = R2.scratchReg();
     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), genObj);
 
     MOZ_ASSERT(GET_UINT24(pc) == 0);
-    masm.storeValue(Int32Value(0), Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()));
+    masm.storeValue(Int32Value(0),
+                    Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
 
     Register envObj = R0.scratchReg();
     Address envChainSlot(genObj, GeneratorObject::offsetOfEnvironmentChainSlot());
     masm.loadPtr(frame.addressOfEnvironmentChain(), envObj);
     masm.patchableCallPreBarrier(envChainSlot, MIRType::Value);
     masm.storeValue(JSVAL_TYPE_OBJECT, envObj, envChainSlot);
 
     Register temp = R1.scratchReg();
@@ -4232,34 +4234,34 @@ BaselineCompiler::emit_JSOP_INITIALYIELD
 
 typedef bool (*NormalSuspendFn)(JSContext*, HandleObject, BaselineFrame*, jsbytecode*, uint32_t);
 static const VMFunction NormalSuspendInfo =
     FunctionInfo<NormalSuspendFn>(jit::NormalSuspend, "NormalSuspend");
 
 bool
 BaselineCompiler::emit_JSOP_YIELD()
 {
-    if (!addYieldOffset())
+    if (!addYieldAndAwaitOffset())
         return false;
 
     // Store generator in R0.
     frame.popRegsAndSync(1);
 
     Register genObj = R2.scratchReg();
     masm.unboxObject(R0, genObj);
 
     MOZ_ASSERT(frame.stackDepth() >= 1);
 
     if (frame.stackDepth() == 1 && !script->isLegacyGenerator()) {
         // If the expression stack is empty, we can inline the YIELD. Don't do
         // this for legacy generators: we have to throw an exception if the
         // generator is in the closing state, see GeneratorObject::suspend.
 
         masm.storeValue(Int32Value(GET_UINT24(pc)),
-                        Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()));
+                        Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
 
         Register envObj = R0.scratchReg();
         Address envChainSlot(genObj, GeneratorObject::offsetOfEnvironmentChainSlot());
         masm.loadPtr(frame.addressOfEnvironmentChain(), envObj);
         masm.patchableCallPreBarrier(envChainSlot, MIRType::Value);
         masm.storeValue(JSVAL_TYPE_OBJECT, envObj, envChainSlot);
 
         Register temp = R1.scratchReg();
@@ -4281,16 +4283,22 @@ BaselineCompiler::emit_JSOP_YIELD()
         if (!callVM(NormalSuspendInfo))
             return false;
     }
 
     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), JSReturnOperand);
     return emitReturn();
 }
 
+bool
+BaselineCompiler::emit_JSOP_AWAIT()
+{
+    return emit_JSOP_YIELD();
+}
+
 typedef bool (*DebugAfterYieldFn)(JSContext*, BaselineFrame*);
 static const VMFunction DebugAfterYieldInfo =
     FunctionInfo<DebugAfterYieldFn>(jit::DebugAfterYield, "DebugAfterYield");
 
 bool
 BaselineCompiler::emit_JSOP_DEBUGAFTERYIELD()
 {
     if (!compileDebugInstrumentation_)
@@ -4500,26 +4508,27 @@ BaselineCompiler::emit_JSOP_RESUME()
         masm.storeValue(NullValue(), exprStackSlot);
         regs.add(initLength);
     }
 
     masm.bind(&noExprStack);
     masm.pushValue(retVal);
 
     if (resumeKind == GeneratorObject::NEXT) {
-        // Determine the resume address based on the yieldIndex and the
-        // yieldIndex -> native table in the BaselineScript.
+        // Determine the resume address based on the yieldAndAwaitIndex and the
+        // yieldAndAwaitIndex -> native table in the BaselineScript.
         masm.load32(Address(scratch1, BaselineScript::offsetOfYieldEntriesOffset()), scratch2);
         masm.addPtr(scratch2, scratch1);
-        masm.unboxInt32(Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()), scratch2);
+        masm.unboxInt32(Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()),
+                        scratch2);
         masm.loadPtr(BaseIndex(scratch1, scratch2, ScaleFromElemWidth(sizeof(uintptr_t))), scratch1);
 
         // Mark as running and jump to the generator's JIT code.
-        masm.storeValue(Int32Value(GeneratorObject::YIELD_INDEX_RUNNING),
-                        Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()));
+        masm.storeValue(Int32Value(GeneratorObject::YIELD_AND_AWAIT_INDEX_RUNNING),
+                        Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
         masm.jump(scratch1);
     } else {
         MOZ_ASSERT(resumeKind == GeneratorObject::THROW || resumeKind == GeneratorObject::CLOSE);
 
         // Update the frame's frameSize field.
         masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset),
                                      scratch2);
         masm.movePtr(scratch2, scratch1);
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -202,16 +202,17 @@ namespace jit {
     _(JSOP_ITER)               \
     _(JSOP_MOREITER)           \
     _(JSOP_ISNOITER)           \
     _(JSOP_ENDITER)            \
     _(JSOP_ISGENCLOSING)       \
     _(JSOP_GENERATOR)          \
     _(JSOP_INITIALYIELD)       \
     _(JSOP_YIELD)              \
+    _(JSOP_AWAIT)              \
     _(JSOP_DEBUGAFTERYIELD)    \
     _(JSOP_FINALYIELDRVAL)     \
     _(JSOP_RESUME)             \
     _(JSOP_CALLEE)             \
     _(JSOP_GETRVAL)            \
     _(JSOP_SETRVAL)            \
     _(JSOP_RETRVAL)            \
     _(JSOP_RETURN)             \
@@ -249,19 +250,19 @@ class BaselineCompiler : public Baseline
     // Native code offset right before the frame is popped and the method
     // returned from.
     CodeOffset epilogueOffset_;
 
     // Native code offset right after debug prologue and epilogue, or
     // equivalent positions when debug mode is off.
     CodeOffset postDebugPrologueOffset_;
 
-    // For each INITIALYIELD or YIELD op, this Vector maps the yield index
-    // to the bytecode offset of the next op.
-    Vector<uint32_t>            yieldOffsets_;
+    // For each INITIALYIELD or YIELD or AWAIT op, this Vector maps the yield
+    // index to the bytecode offset of the next op.
+    Vector<uint32_t>            yieldAndAwaitOffsets_;
 
     // Whether any on stack arguments are modified.
     bool modifiesArguments_;
 
     Label* labelOf(jsbytecode* pc) {
         return &labels_[script->pcToOffset(pc)];
     }
 
@@ -343,17 +344,17 @@ class BaselineCompiler : public Baseline
 
     MOZ_MUST_USE bool emitThrowConstAssignment();
     MOZ_MUST_USE bool emitUninitializedLexicalCheck(const ValueOperand& val);
 
     MOZ_MUST_USE bool emitIsMagicValue();
 
     MOZ_MUST_USE bool addPCMappingEntry(bool addIndexEntry);
 
-    MOZ_MUST_USE bool addYieldOffset();
+    MOZ_MUST_USE bool addYieldAndAwaitOffset();
 
     void getEnvironmentCoordinateObject(Register reg);
     Address getEnvironmentCoordinateAddressFromObject(Register objReg, Register reg);
     Address getEnvironmentCoordinateAddress(Register reg);
 };
 
 extern const VMFunction NewArrayCopyOnWriteInfo;
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -3273,22 +3273,23 @@ ICCall_IsSuspendedStarGenerator::Compile
     masm.branchTestObject(Assembler::NotEqual, argVal, &returnFalse);
     masm.unboxObject(argVal, genObj);
 
     // Check if it's a StarGeneratorObject.
     Register scratch = regs.takeAny();
     masm.branchTestObjClass(Assembler::NotEqual, genObj, scratch, &StarGeneratorObject::class_,
                             &returnFalse);
 
-    // If the yield index slot holds an int32 value < YIELD_INDEX_CLOSING,
+    // If the yield index slot holds an int32 value < YIELD_AND_AWAIT_INDEX_CLOSING,
     // the generator is suspended.
-    masm.loadValue(Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()), argVal);
+    masm.loadValue(Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()), argVal);
     masm.branchTestInt32(Assembler::NotEqual, argVal, &returnFalse);
     masm.unboxInt32(argVal, scratch);
-    masm.branch32(Assembler::AboveOrEqual, scratch, Imm32(StarGeneratorObject::YIELD_INDEX_CLOSING),
+    masm.branch32(Assembler::AboveOrEqual, scratch,
+                  Imm32(StarGeneratorObject::YIELD_AND_AWAIT_INDEX_CLOSING),
                   &returnFalse);
 
     masm.moveValue(BooleanValue(true), R0);
     EmitReturnFromIC(masm);
 
     masm.bind(&returnFalse);
     masm.moveValue(BooleanValue(false), R0);
     EmitReturnFromIC(masm);
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -762,22 +762,22 @@ BaselineScript::icEntryFromReturnAddress
 {
     MOZ_ASSERT(returnAddr > method_->raw());
     MOZ_ASSERT(returnAddr < method_->raw() + method_->instructionsSize());
     CodeOffset offset(returnAddr - method_->raw());
     return icEntryFromReturnOffset(offset);
 }
 
 void
-BaselineScript::copyYieldEntries(JSScript* script, Vector<uint32_t>& yieldOffsets)
+BaselineScript::copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets)
 {
     uint8_t** entries = yieldEntryList();
 
-    for (size_t i = 0; i < yieldOffsets.length(); i++) {
-        uint32_t offset = yieldOffsets[i];
+    for (size_t i = 0; i < yieldAndAwaitOffsets.length(); i++) {
+        uint32_t offset = yieldAndAwaitOffsets[i];
         entries[i] = nativeCodeForPC(script, script->offsetToPC(offset));
     }
 }
 
 void
 BaselineScript::copyICEntries(JSScript* script, const BaselineICEntry* entries, MacroAssembler& masm)
 {
     // Fix up the return offset in the IC entries and copy them in.
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -395,17 +395,17 @@ struct BaselineScript
 
     size_t numICEntries() const {
         return icEntries_;
     }
 
     void copyICEntries(JSScript* script, const BaselineICEntry* entries, MacroAssembler& masm);
     void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
 
-    void copyYieldEntries(JSScript* script, Vector<uint32_t>& yieldOffsets);
+    void copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets);
 
     PCMappingIndexEntry& pcMappingIndexEntry(size_t index);
     CompactBufferReader pcMappingReader(size_t indexEntry);
 
     size_t numPCMappingIndexEntries() const {
         return pcMappingIndexEntries_;
     }
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2354,17 +2354,19 @@ IonCompile(JSContext* cx, JSScript* scri
     if (cx->isExceptionPending())
         return AbortReason::Error;
     return AbortReason::Disable;
 }
 
 static bool
 CheckFrame(JSContext* cx, BaselineFrame* frame)
 {
-    MOZ_ASSERT(!frame->script()->isGenerator());
+    MOZ_ASSERT(!frame->script()->isStarGenerator());
+    MOZ_ASSERT(!frame->script()->isLegacyGenerator());
+    MOZ_ASSERT(!frame->script()->isAsync());
     MOZ_ASSERT(!frame->isDebuggerEvalFrame());
     MOZ_ASSERT(!frame->isEvalFrame());
 
     // This check is to not overrun the stack.
     if (frame->isFunctionFrame()) {
         if (TooManyActualArguments(frame->numActualArgs())) {
             TrackAndSpewIonAbort(cx, frame->script(), "too many actual arguments");
             return false;
@@ -2385,20 +2387,24 @@ CheckScript(JSContext* cx, JSScript* scr
     if (script->isForEval()) {
         // Eval frames are not yet supported. Supporting this will require new
         // logic in pushBailoutFrame to deal with linking prev.
         // Additionally, JSOP_DEFVAR support will require baking in isEvalFrame().
         TrackAndSpewIonAbort(cx, script, "eval script");
         return false;
     }
 
-    if (script->isGenerator()) {
+    if (script->isStarGenerator() || script->isLegacyGenerator()) {
         TrackAndSpewIonAbort(cx, script, "generator script");
         return false;
     }
+    if (script->isAsync()) {
+        TrackAndSpewIonAbort(cx, script, "async script");
+        return false;
+    }
 
     if (script->hasNonSyntacticScope() && !script->functionNonDelazifying()) {
         // Support functions with a non-syntactic global scope but not other
         // scripts. For global scripts, IonBuilder currently uses the global
         // object as scope chain, this is not valid when the script has a
         // non-syntactic global scope.
         TrackAndSpewIonAbort(cx, script, "has non-syntactic global scope");
         return false;
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4401,18 +4401,24 @@ jit::AnalyzeArgumentsUsage(JSContext* cx
     // and also simplifies handling of early returns.
     script->setNeedsArgsObj(true);
 
     // Always construct arguments objects when in debug mode, for generator
     // scripts (generators can be suspended when speculation fails) or when
     // direct eval is present.
     //
     // FIXME: Don't build arguments for ES6 generator expressions.
-    if (scriptArg->isDebuggee() || script->isGenerator() || script->bindingsAccessedDynamically())
+    if (scriptArg->isDebuggee() ||
+        script->isStarGenerator() ||
+        script->isLegacyGenerator() ||
+        script->isAsync() ||
+        script->bindingsAccessedDynamically())
+    {
         return true;
+    }
 
     if (!jit::IsIonEnabled(cx))
         return true;
 
     static const uint32_t MAX_SCRIPT_SIZE = 10000;
     if (script->length() > MAX_SCRIPT_SIZE)
         return true;
 
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -129,16 +129,20 @@ class MOZ_NON_PARAM RInstruction
 
     // As opposed to the MIR, there is no need to add more methods as every
     // other instruction is well abstracted under the "recover" method.
     bool isResumePoint() const {
         return opcode() == Recover_ResumePoint;
     }
     inline const RResumePoint* toResumePoint() const;
 
+    // Call the copy constructor of a specific RInstruction, to do a copy of the
+    // RInstruction content.
+    virtual void cloneInto(RInstructionStorage* raw) const = 0;
+
     // Number of allocations which are encoded in the Snapshot for recovering
     // the current instruction.
     virtual uint32_t numOperands() const = 0;
 
     // Function used to recover the value computed by this instruction. This
     // function reads its arguments from the allocations listed on the snapshot
     // iterator and stores its returned value on the snapshot iterator too.
     virtual MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const = 0;
@@ -148,25 +152,29 @@ class MOZ_NON_PARAM RInstruction
     // instruction.
     static void readRecoverData(CompactBufferReader& reader, RInstructionStorage* raw);
 };
 
 #define RINSTRUCTION_HEADER_(op)                                        \
   private:                                                              \
     friend class RInstruction;                                          \
     explicit R##op(CompactBufferReader& reader);                        \
+    explicit R##op(const R##op& src) = default;                         \
                                                                         \
   public:                                                               \
-    Opcode opcode() const {                                             \
+    Opcode opcode() const override {                                    \
         return RInstruction::Recover_##op;                              \
+    }                                                                   \
+    void cloneInto(RInstructionStorage* raw) const override {           \
+        new (raw->addr()) R##op(*this);                                 \
     }
 
 #define RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp)                      \
     RINSTRUCTION_HEADER_(op)                                            \
-    virtual uint32_t numOperands() const {                              \
+    uint32_t numOperands() const override {                             \
         return numOp;                                                   \
     }
 
 #ifdef DEBUG
 # define RINSTRUCTION_HEADER_NUM_OP_(op, numOp)                         \
     RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp)                          \
     static_assert(M##op::staticNumOperands == numOp, "The recover instructions's numOperands should equal to the MIR's numOperands");
 #else
@@ -181,503 +189,503 @@ class RResumePoint final : public RInstr
     uint32_t numOperands_;        // Number of slots.
 
   public:
     RINSTRUCTION_HEADER_(ResumePoint)
 
     uint32_t pcOffset() const {
         return pcOffset_;
     }
-    virtual uint32_t numOperands() const {
+    uint32_t numOperands() const override {
         return numOperands_;
     }
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RBitNot final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(BitNot, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RBitAnd final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(BitAnd, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RBitOr final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(BitOr, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RBitXor final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(BitXor, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RLsh final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Lsh, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RRsh final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Rsh, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RUrsh final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Ursh, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RSignExtend final : public RInstruction
 {
   private:
     uint8_t mode_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(SignExtend, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RAdd final : public RInstruction
 {
   private:
     bool isFloatOperation_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Add, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RSub final : public RInstruction
 {
   private:
     bool isFloatOperation_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Sub, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RMul final : public RInstruction
 {
   private:
     bool isFloatOperation_;
     uint8_t mode_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Mul, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RDiv final : public RInstruction
 {
   private:
     bool isFloatOperation_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Div, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RMod final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Mod, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RNot final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Not, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RConcat final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Concat, 2)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RStringLength final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(StringLength, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RArgumentsLength final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(ArgumentsLength, 0)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 
 class RFloor final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Floor, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
 };
 
 class RCeil final : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_NUM_OP_(Ceil, 1)
 
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
+    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;