author | Wes Kocher <wkocher@mozilla.com> |
Wed, 01 Mar 2017 17:18:37 -0800 | |
changeset 345391 | e91de6fb2b3dce9c932428265b0fdb630ea470d7 |
parent 345390 | e150eaff1f83e4e4a97d1e30c57d233859efe9cb (current diff) |
parent 345355 | f3b989e0a7b90950c47dd72425c7f669f027c685 (diff) |
child 345392 | c688b2234591df521e868c5938d63d63135ab272 |
child 345565 | 20f706c6244a69638d90d14eb5b0ea7bd873942c |
push id | 87590 |
push user | kwierso@gmail.com |
push date | Thu, 02 Mar 2017 01:48:14 +0000 |
treeherder | mozilla-inbound@c688b2234591 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 54.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
54.0a1
/
20170302110226
/
pushlog to previous
nightly linux64
54.0a1
/
20170302110226
/
pushlog to previous
nightly mac
54.0a1
/
20170302030206
/
pushlog to previous
nightly win32
54.0a1
/
20170302030206
/
pushlog to previous
nightly win64
54.0a1
/
20170302030206
/
pushlog to previous
|
--- 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; };