Merge mozilla-inbound to mozilla-central. a=merge

This commit is contained in:
Cosmin Sabou 2018-12-13 05:56:48 +02:00
commit 9835fdf72c
43 changed files with 267 additions and 198 deletions

View File

@ -1,9 +1,9 @@
This is the debugger.html project output. This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html See https://github.com/devtools-html/debugger.html
Version 106 Version 107
Comparison: https://github.com/devtools-html/debugger.html/compare/release-105...release-106 Comparison: https://github.com/devtools-html/debugger.html/compare/release-106...release-107
Packages: Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2 - babel-plugin-transform-es2015-modules-commonjs @6.26.2

View File

@ -2,14 +2,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/>. */ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// @flow
import { getSourceFromId } from "../../selectors"; import { getSourceFromId } from "../../selectors";
import * as parser from "../../workers/parser"; import * as parser from "../../workers/parser";
import { isGenerated } from "../../utils/source"; import { isGenerated } from "../../utils/source";
import { mapPausePoints } from "../../utils/pause/pausePoints"; import { mapPausePoints } from "../../utils/pause/pausePoints";
import { features } from "../../utils/prefs"; import { features } from "../../utils/prefs";
import type { SourceId } from "../types"; import type { SourceId } from "../../types";
import type { ThunkArgs, Action } from "./types"; import type { ThunkArgs, Action } from "../types";
function compressPausePoints(pausePoints) { function compressPausePoints(pausePoints) {
const compressed = {}; const compressed = {};

View File

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/>. */ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// @flow
import { isOriginalId } from "devtools-source-map"; import { isOriginalId } from "devtools-source-map";
import { import {
locationMoved, locationMoved,
@ -17,10 +19,18 @@ import { getGeneratedLocation } from "../../utils/source-maps";
import { getTextAtPosition } from "../../utils/source"; import { getTextAtPosition } from "../../utils/source";
import { recordEvent } from "../../utils/telemetry"; import { recordEvent } from "../../utils/telemetry";
import type { SourceLocation } from "../../types";
import type { ThunkArgs } from "../types";
import type { addBreakpointOptions } from "./";
async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) { async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
const state = getState(); const state = getState();
const source = getSource(state, breakpoint.location.sourceId); const source = getSource(state, breakpoint.location.sourceId);
if (!source) {
throw new Error(`Unable to find source: ${breakpoint.location.sourceId}`);
}
const location = { const location = {
...breakpoint.location, ...breakpoint.location,
sourceId: source.id, sourceId: source.id,

View File

@ -36,7 +36,7 @@ import type { Breakpoint, SourceLocation, XHRBreakpoint } from "../../types";
import { recordEvent } from "../../utils/telemetry"; import { recordEvent } from "../../utils/telemetry";
type addBreakpointOptions = { export type addBreakpointOptions = {
condition?: string, condition?: string,
hidden?: boolean hidden?: boolean
}; };
@ -264,12 +264,12 @@ export function setBreakpointCondition(
}; };
} }
export function toggleBreakpoint(line: ?number, column?: number) { export function toggleBreakpoint(line: number, column?: number) {
return ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => { return ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
const state = getState(); const state = getState();
const selectedSource = getSelectedSource(state); const selectedSource = getSelectedSource(state);
if (!line || !selectedSource) { if (!selectedSource) {
return; return;
} }
@ -307,7 +307,7 @@ export function toggleBreakpointsAtLine(line: number, column?: number) {
const state = getState(); const state = getState();
const selectedSource = getSelectedSource(state); const selectedSource = getSelectedSource(state);
if (!line || !selectedSource) { if (!selectedSource) {
return; return;
} }
@ -329,11 +329,11 @@ export function toggleBreakpointsAtLine(line: number, column?: number) {
}; };
} }
export function addOrToggleDisabledBreakpoint(line: ?number, column?: number) { export function addOrToggleDisabledBreakpoint(line: number, column?: number) {
return ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => { return ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
const selectedSource = getSelectedSource(getState()); const selectedSource = getSelectedSource(getState());
if (!line || !selectedSource) { if (!selectedSource) {
return; return;
} }

View File

@ -17,6 +17,7 @@ import type { ThunkArgs, panelPositionType } from "./types";
import { getEditor, getLocationsInViewport } from "../utils/editor"; import { getEditor, getLocationsInViewport } from "../utils/editor";
import { searchContents } from "./file-search"; import { searchContents } from "./file-search";
import type { SourceLocation } from "../types";
import type { import type {
ActiveSearchType, ActiveSearchType,
OrientationType, OrientationType,
@ -155,14 +156,14 @@ export function clearHighlightLineRange() {
}; };
} }
export function openConditionalPanel(line: ?number) { export function openConditionalPanel(location: ?SourceLocation) {
if (!line) { if (!location) {
return; return;
} }
return { return {
type: "OPEN_CONDITIONAL_PANEL", type: "OPEN_CONDITIONAL_PANEL",
line location
}; };
} }

View File

@ -11,16 +11,16 @@ import { toEditorLine } from "../../utils/editor";
import actions from "../../actions"; import actions from "../../actions";
import { import {
getSelectedLocation, getBreakpointForLocation,
getBreakpointForLine, getConditionalPanelLocation
getConditionalPanelLine
} from "../../selectors"; } from "../../selectors";
import type { SourceLocation } from "../../types";
type Props = { type Props = {
breakpoint: ?Object, breakpoint: ?Object,
selectedLocation: Object,
setBreakpointCondition: Function, setBreakpointCondition: Function,
line: number, location: SourceLocation,
editor: Object, editor: Object,
openConditionalPanel: () => void, openConditionalPanel: () => void,
closeConditionalPanel: () => void closeConditionalPanel: () => void
@ -60,9 +60,7 @@ export class ConditionalPanel extends PureComponent<Props> {
}; };
setBreakpoint(condition: string) { setBreakpoint(condition: string) {
const { selectedLocation, line } = this.props; const { location } = this.props;
const sourceId = selectedLocation ? selectedLocation.sourceId : "";
const location = { sourceId, line };
return this.props.setBreakpointCondition(location, { condition }); return this.props.setBreakpointCondition(location, { condition });
} }
@ -84,15 +82,10 @@ export class ConditionalPanel extends PureComponent<Props> {
}; };
componentWillMount() { componentWillMount() {
if (this.props.line) { return this.renderToWidget(this.props);
return this.renderToWidget(this.props);
}
} }
componentWillUpdate(nextProps: Props) { componentWillUpdate() {
if (nextProps.line) {
return this.renderToWidget(nextProps);
}
return this.clearConditionalPanel(); return this.clearConditionalPanel();
} }
@ -109,16 +102,12 @@ export class ConditionalPanel extends PureComponent<Props> {
renderToWidget(props: Props) { renderToWidget(props: Props) {
if (this.cbPanel) { if (this.cbPanel) {
if (this.props.line && this.props.line == props.line) {
return props.closeConditionalPanel();
}
this.clearConditionalPanel(); this.clearConditionalPanel();
} }
const { selectedLocation, line, editor } = props; const { location, editor } = props;
const sourceId = selectedLocation ? selectedLocation.sourceId : "";
const editorLine = toEditorLine(sourceId, line); const editorLine = toEditorLine(location.sourceId, location.line || 0);
this.cbPanel = editor.codeMirror.addLineWidget( this.cbPanel = editor.codeMirror.addLineWidget(
editorLine, editorLine,
this.renderConditionalPanel(props), this.renderConditionalPanel(props),
@ -180,13 +169,11 @@ export class ConditionalPanel extends PureComponent<Props> {
} }
const mapStateToProps = state => { const mapStateToProps = state => {
const line = getConditionalPanelLine(state); const location = getConditionalPanelLocation(state);
const selectedLocation = getSelectedLocation(state);
return { return {
selectedLocation, breakpoint: getBreakpointForLocation(state, location),
breakpoint: getBreakpointForLine(state, selectedLocation.sourceId, line), location
line
}; };
}; };

View File

@ -203,10 +203,6 @@ function getMenuItems(
class EditorMenu extends Component { class EditorMenu extends Component {
props: Props; props: Props;
constructor() {
super();
}
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
return nextProps.contextMenu.type === "Editor"; return nextProps.contextMenu.type === "Editor";
} }

View File

@ -32,7 +32,8 @@ export function gutterMenu({
toggleDisabledBreakpoint, toggleDisabledBreakpoint,
isCbPanelOpen, isCbPanelOpen,
closeConditionalPanel, closeConditionalPanel,
continueToHere continueToHere,
sourceId
}) { }) {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -84,7 +85,11 @@ export function gutterMenu({
const conditionalBreakpoint = { const conditionalBreakpoint = {
accesskey: L10N.getStr("editor.addConditionalBreakpoint.accesskey"), accesskey: L10N.getStr("editor.addConditionalBreakpoint.accesskey"),
disabled: false, disabled: false,
click: () => openConditionalPanel(line), // Leaving column undefined so pause points can be detected
click: () =>
openConditionalPanel(
breakpoint ? breakpoint.location : { line, sourceId }
),
accelerator: L10N.getStr("toggleCondPanel.key"), accelerator: L10N.getStr("toggleCondPanel.key"),
...(breakpoint && breakpoint.condition ...(breakpoint && breakpoint.condition
? gutterItems.editConditional ? gutterItems.editConditional
@ -121,10 +126,6 @@ export function gutterMenu({
class GutterContextMenuComponent extends Component { class GutterContextMenuComponent extends Component {
props: Props; props: Props;
constructor() {
super();
}
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
return nextProps.contextMenu.type === "Gutter"; return nextProps.contextMenu.type === "Gutter";
} }

View File

@ -16,10 +16,6 @@ type Props = {
class HighlightLines extends Component<Props> { class HighlightLines extends Component<Props> {
highlightLineRange: Function; highlightLineRange: Function;
constructor() {
super();
}
componentDidMount() { componentDidMount() {
this.highlightLineRange(); this.highlightLineRange();
} }

View File

@ -20,7 +20,7 @@ import {
getActiveSearch, getActiveSearch,
getSelectedLocation, getSelectedLocation,
getSelectedSource, getSelectedSource,
getConditionalPanelLine, getConditionalPanelLocation,
getSymbols getSymbols
} from "../../selectors"; } from "../../selectors";
@ -81,17 +81,17 @@ export type Props = {
horizontal: boolean, horizontal: boolean,
startPanelSize: number, startPanelSize: number,
endPanelSize: number, endPanelSize: number,
conditionalPanelLine: number, conditionalPanelLocation: SourceLocation,
symbols: SymbolDeclarations, symbols: SymbolDeclarations,
// Actions // Actions
openConditionalPanel: (?number) => void, openConditionalPanel: (?SourceLocation) => void,
closeConditionalPanel: void => void, closeConditionalPanel: void => void,
setContextMenu: (string, any) => void, setContextMenu: (string, any) => void,
continueToHere: (?number) => void, continueToHere: number => void,
toggleBreakpoint: (?number) => void, toggleBreakpoint: number => void,
toggleBreakpointsAtLine: (?number) => void, toggleBreakpointsAtLine: number => void,
addOrToggleDisabledBreakpoint: (?number) => void, addOrToggleDisabledBreakpoint: number => void,
jumpToMappedLocation: any => void, jumpToMappedLocation: any => void,
traverseResults: (boolean, Object) => void, traverseResults: (boolean, Object) => void,
updateViewport: void => void updateViewport: void => void
@ -256,17 +256,20 @@ class Editor extends PureComponent<Props, State> {
onToggleBreakpoint = (key, e: KeyboardEvent) => { onToggleBreakpoint = (key, e: KeyboardEvent) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const { selectedSource, conditionalPanelLine } = this.props; const { selectedSource, conditionalPanelLocation } = this.props;
if (!selectedSource) { if (!selectedSource) {
return; return;
} }
const line = this.getCurrentLine(); const line = this.getCurrentLine();
if (typeof line !== "number") {
return;
}
if (e.shiftKey) { if (e.shiftKey) {
this.toggleConditionalPanel(line); this.toggleConditionalPanel(line);
} else if (!conditionalPanelLine) { } else if (!conditionalPanelLocation) {
this.props.toggleBreakpoint(line); this.props.toggleBreakpoint(line);
} else { } else {
this.toggleConditionalPanel(line); this.toggleConditionalPanel(line);
@ -278,6 +281,10 @@ class Editor extends PureComponent<Props, State> {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
const line = this.getCurrentLine(); const line = this.getCurrentLine();
if (typeof line !== "number") {
return;
}
this.toggleConditionalPanel(line); this.toggleConditionalPanel(line);
}; };
@ -343,7 +350,7 @@ class Editor extends PureComponent<Props, State> {
) => { ) => {
const { const {
selectedSource, selectedSource,
conditionalPanelLine, conditionalPanelLocation,
closeConditionalPanel, closeConditionalPanel,
addOrToggleDisabledBreakpoint, addOrToggleDisabledBreakpoint,
toggleBreakpointsAtLine, toggleBreakpointsAtLine,
@ -360,7 +367,7 @@ class Editor extends PureComponent<Props, State> {
return; return;
} }
if (conditionalPanelLine) { if (conditionalPanelLocation) {
return closeConditionalPanel(); return closeConditionalPanel();
} }
@ -369,6 +376,9 @@ class Editor extends PureComponent<Props, State> {
} }
const sourceLine = toSourceLine(selectedSource.id, line); const sourceLine = toSourceLine(selectedSource.id, line);
if (typeof sourceLine !== "number") {
return;
}
if (ev.metaKey) { if (ev.metaKey) {
return continueToHere(sourceLine); return continueToHere(sourceLine);
@ -402,16 +412,16 @@ class Editor extends PureComponent<Props, State> {
toggleConditionalPanel = line => { toggleConditionalPanel = line => {
const { const {
conditionalPanelLine, conditionalPanelLocation,
closeConditionalPanel, closeConditionalPanel,
openConditionalPanel openConditionalPanel
} = this.props; } = this.props;
if (conditionalPanelLine) { if (conditionalPanelLocation) {
return closeConditionalPanel(); return closeConditionalPanel();
} }
return openConditionalPanel(line); return openConditionalPanel(conditionalPanelLocation);
}; };
closeConditionalPanel = () => { closeConditionalPanel = () => {
@ -535,7 +545,7 @@ class Editor extends PureComponent<Props, State> {
} }
renderItems() { renderItems() {
const { horizontal, selectedSource } = this.props; const { horizontal, selectedSource, conditionalPanelLocation } = this.props;
const { editor } = this.state; const { editor } = this.state;
if (!editor || !selectedSource) { if (!editor || !selectedSource) {
@ -553,7 +563,7 @@ class Editor extends PureComponent<Props, State> {
<HighlightLines editor={editor} /> <HighlightLines editor={editor} />
<EditorMenu editor={editor} /> <EditorMenu editor={editor} />
<GutterMenu editor={editor} /> <GutterMenu editor={editor} />
<ConditionalPanel editor={editor} /> {conditionalPanelLocation ? <ConditionalPanel editor={editor} /> : null}
{features.columnBreakpoints ? ( {features.columnBreakpoints ? (
<ColumnBreakpoints editor={editor} /> <ColumnBreakpoints editor={editor} />
) : null} ) : null}
@ -599,7 +609,7 @@ const mapStateToProps = state => {
selectedLocation: getSelectedLocation(state), selectedLocation: getSelectedLocation(state),
selectedSource, selectedSource,
searchOn: getActiveSearch(state) === "file", searchOn: getActiveSearch(state) === "file",
conditionalPanelLine: getConditionalPanelLine(state), conditionalPanelLocation: getConditionalPanelLocation(state),
symbols: getSymbols(state, selectedSource) symbols: getSymbols(state, selectedSource)
}; };
}; };

View File

@ -126,15 +126,11 @@ export class QuickOpenModal extends Component<Props, State> {
searchSymbols = (query: string) => { searchSymbols = (query: string) => {
const { const {
symbols: { functions, identifiers } symbols: { functions }
} = this.props; } = this.props;
let results = functions; let results = functions;
if (this.isVariableQuery()) { results = results.filter(result => result.title !== "anonymous");
results = identifiers;
} else {
results = results.filter(result => result.title !== "anonymous");
}
if (query === "@" || query === "#") { if (query === "@" || query === "#") {
return this.setState({ results }); return this.setState({ results });
@ -219,24 +215,11 @@ export class QuickOpenModal extends Component<Props, State> {
}; };
onSelectResultItem = (item: QuickOpenResult) => { onSelectResultItem = (item: QuickOpenResult) => {
const { const { selectedSource, highlightLineRange } = this.props;
selectSpecificLocation,
selectedSource,
highlightLineRange
} = this.props;
if (!this.isSymbolSearch() || selectedSource == null) { if (!this.isSymbolSearch() || selectedSource == null) {
return; return;
} }
if (this.isVariableQuery()) {
const line =
item.location && item.location.start ? item.location.start.line : 0;
return selectSpecificLocation({
sourceId: selectedSource.id,
line
});
}
if (this.isFunctionQuery()) { if (this.isFunctionQuery()) {
return highlightLineRange({ return highlightLineRange({
...(item.location != null ...(item.location != null
@ -322,8 +305,7 @@ export class QuickOpenModal extends Component<Props, State> {
// Query helpers // Query helpers
isFunctionQuery = () => this.props.searchType === "functions"; isFunctionQuery = () => this.props.searchType === "functions";
isVariableQuery = () => this.props.searchType === "variables"; isSymbolSearch = () => this.isFunctionQuery();
isSymbolSearch = () => this.isFunctionQuery() || this.isVariableQuery();
isGotoQuery = () => this.props.searchType === "goto"; isGotoQuery = () => this.props.searchType === "goto";
isGotoSourceQuery = () => this.props.searchType === "gotoSource"; isGotoSourceQuery = () => this.props.searchType === "gotoSource";
isShortcutQuery = () => this.props.searchType === "shortcuts"; isShortcutQuery = () => this.props.searchType === "shortcuts";
@ -379,10 +361,7 @@ export class QuickOpenModal extends Component<Props, State> {
let summaryMsg = ""; let summaryMsg = "";
if (this.isGotoQuery()) { if (this.isGotoQuery()) {
summaryMsg = L10N.getStr("shortcuts.gotoLine"); summaryMsg = L10N.getStr("shortcuts.gotoLine");
} else if ( } else if (this.isFunctionQuery() && this.props.symbolsLoading) {
(this.isFunctionQuery() || this.isVariableQuery()) &&
this.props.symbolsLoading
) {
summaryMsg = L10N.getStr("loadingText"); summaryMsg = L10N.getStr("loadingText");
} }
return summaryMsg; return summaryMsg;

View File

@ -65,7 +65,7 @@ class Breakpoint extends PureComponent<Props> {
onDoubleClick = () => { onDoubleClick = () => {
const { breakpoint, openConditionalPanel } = this.props; const { breakpoint, openConditionalPanel } = this.props;
if (breakpoint.condition) { if (breakpoint.condition) {
openConditionalPanel(breakpoint.selectedLocation.line); openConditionalPanel(breakpoint.selectedLocation);
} }
}; };

View File

@ -2,10 +2,33 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/>. */ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// @flow
import { buildMenu, showMenu } from "devtools-contextmenu"; import { buildMenu, showMenu } from "devtools-contextmenu";
export default function showContextMenu(props) { import actions from "../../../actions";
import type { Breakpoint } from "../../../types";
import type { FormattedBreakpoint } from "../../../selectors/breakpointSources";
type Props = {
breakpoint: FormattedBreakpoint,
breakpoints: Breakpoint[],
removeBreakpoint: typeof actions.removeBreakpoint,
removeBreakpoints: typeof actions.removeBreakpoints,
removeAllBreakpoints: typeof actions.removeAllBreakpoints,
toggleBreakpoints: typeof actions.toggleBreakpoints,
toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
toggleDisabledBreakpoint: typeof actions.toggleDisabledBreakpoint,
selectSpecificLocation: typeof actions.selectSpecificLocation,
setBreakpointCondition: typeof actions.setBreakpointCondition,
openConditionalPanel: typeof actions.openConditionalPanel,
contextMenuEvent: SyntheticEvent<HTMLElement>
};
export default function showContextMenu(props: Props) {
const { const {
breakpoint,
breakpoints,
removeBreakpoint, removeBreakpoint,
removeBreakpoints, removeBreakpoints,
removeAllBreakpoints, removeAllBreakpoints,
@ -15,8 +38,6 @@ export default function showContextMenu(props) {
selectSpecificLocation, selectSpecificLocation,
setBreakpointCondition, setBreakpointCondition,
openConditionalPanel, openConditionalPanel,
breakpoints,
breakpoint,
contextMenuEvent contextMenuEvent
} = props; } = props;
@ -169,7 +190,7 @@ export default function showContextMenu(props) {
accesskey: addConditionKey, accesskey: addConditionKey,
click: () => { click: () => {
selectSpecificLocation(breakpoint.selectedLocation); selectSpecificLocation(breakpoint.selectedLocation);
openConditionalPanel(breakpoint.selectedLocation.line); openConditionalPanel(breakpoint.selectedLocation);
} }
}; };
@ -179,7 +200,7 @@ export default function showContextMenu(props) {
accesskey: editConditionKey, accesskey: editConditionKey,
click: () => { click: () => {
selectSpecificLocation(breakpoint.selectedLocation); selectSpecificLocation(breakpoint.selectedLocation);
openConditionalPanel(breakpoint.selectedLocation.line); openConditionalPanel(breakpoint.selectedLocation);
} }
}; };

View File

@ -79,7 +79,7 @@ export default class Group extends Component<Props, State> {
); );
} }
toggleFrames = (event) => { toggleFrames = event => {
event.stopPropagation(); event.stopPropagation();
this.setState(prevState => ({ expanded: !prevState.expanded })); this.setState(prevState => ({ expanded: !prevState.expanded }));
}; };

View File

@ -38,6 +38,12 @@ type State = {
focused: boolean focused: boolean
}; };
// At present, the "Pause on any URL" checkbox creates an xhrBreakpoint
// of "ANY" with no path, so we can remove that before creating the list
function getExplicitXHRBreakpoints(xhrBreakpoints) {
return xhrBreakpoints.filter(bp => bp.path !== "");
}
class XHRBreakpoints extends Component<Props, State> { class XHRBreakpoints extends Component<Props, State> {
_input: ?HTMLInputElement; _input: ?HTMLInputElement;
@ -207,10 +213,7 @@ class XHRBreakpoints extends Component<Props, State> {
renderBreakpoints = () => { renderBreakpoints = () => {
const { showInput, xhrBreakpoints } = this.props; const { showInput, xhrBreakpoints } = this.props;
const explicitXhrBreakpoints = getExplicitXHRBreakpoints(xhrBreakpoints);
// At present, the "Pause on any URL" checkbox creates an xhrBreakpoint
// of "ANY" with no path, so we can remove that before creating the list
const explicitXhrBreakpoints = xhrBreakpoints.filter(bp => bp.path !== "");
return ( return (
<ul className="pane expressions-list"> <ul className="pane expressions-list">
@ -223,11 +226,12 @@ class XHRBreakpoints extends Component<Props, State> {
renderCheckbox = () => { renderCheckbox = () => {
const { shouldPauseOnAny, togglePauseOnAny, xhrBreakpoints } = this.props; const { shouldPauseOnAny, togglePauseOnAny, xhrBreakpoints } = this.props;
const explicitXhrBreakpoints = getExplicitXHRBreakpoints(xhrBreakpoints);
return ( return (
<div <div
className={classnames("breakpoints-exceptions-options", { className={classnames("breakpoints-exceptions-options", {
empty: xhrBreakpoints.size === 0 empty: explicitXhrBreakpoints.size === 0
})} })}
> >
<ExceptionOption <ExceptionOption

View File

@ -28,10 +28,6 @@ export default class ResultList extends Component<Props> {
role: "listbox" role: "listbox"
}; };
constructor(props: Props) {
super(props);
}
renderListItem = (item: any, index: number) => { renderListItem = (item: any, index: number) => {
if (item.value === "/" && item.title === "") { if (item.value === "/" && item.title === "") {
item.title = "(index)"; item.title = "(index)";

View File

@ -12,6 +12,8 @@
import * as I from "immutable"; import * as I from "immutable";
import { isGeneratedId } from "devtools-source-map"; import { isGeneratedId } from "devtools-source-map";
import { isEqual } from "lodash";
import { makeLocationId } from "../utils/breakpoint"; import { makeLocationId } from "../utils/breakpoint";
import type { XHRBreakpoint, Breakpoint, SourceLocation } from "../types"; import type { XHRBreakpoint, Breakpoint, SourceLocation } from "../types";
@ -251,6 +253,10 @@ function removeBreakpoint(state, action): BreakpointsState {
return unsetBreakpoint(state, id); return unsetBreakpoint(state, id);
} }
function isMatchingLocation(location1, location2) {
return isEqual(location1, location2);
}
// Selectors // Selectors
// TODO: these functions should be moved out of the reducer // TODO: these functions should be moved out of the reducer
@ -305,16 +311,20 @@ export function getBreakpointsForSource(
}); });
} }
export function getBreakpointForLine( export function getBreakpointForLocation(
state: OuterState, state: OuterState,
sourceId: string, location: SourceLocation | null
line: number | null
): ?Breakpoint { ): ?Breakpoint {
if (!sourceId) { if (!location || !location.sourceId) {
return undefined; return undefined;
} }
const loc = { ...location };
const breakpoints = getBreakpointsList(state); const breakpoints = getBreakpointsList(state);
return breakpoints.find(breakpoint => breakpoint.location.line === line); return breakpoints.find(breakpoint =>
isMatchingLocation(loc, breakpoint.location)
);
} }
export function getHiddenBreakpoint(state: OuterState): ?Breakpoint { export function getHiddenBreakpoint(state: OuterState): ?Breakpoint {

View File

@ -12,12 +12,7 @@ import { parseQuickOpenQuery } from "../utils/quick-open";
import type { Action } from "../actions/types"; import type { Action } from "../actions/types";
import type { Record } from "../utils/makeRecord"; import type { Record } from "../utils/makeRecord";
export type QuickOpenType = export type QuickOpenType = "sources" | "functions" | "goto" | "gotoSource";
| "sources"
| "functions"
| "variables"
| "goto"
| "gotoSource";
type QuickOpenState = { type QuickOpenState = {
enabled: boolean, enabled: boolean,

View File

@ -12,7 +12,7 @@
import makeRecord from "../utils/makeRecord"; import makeRecord from "../utils/makeRecord";
import { prefs } from "../utils/prefs"; import { prefs } from "../utils/prefs";
import type { Source, PartialRange } from "../types"; import type { Source, PartialRange, SourceLocation } from "../types";
import type { Action, panelPositionType } from "../actions/types"; import type { Action, panelPositionType } from "../actions/types";
import type { Record } from "../utils/makeRecord"; import type { Record } from "../utils/makeRecord";
@ -40,7 +40,7 @@ export type UIState = {
end?: number, end?: number,
sourceId?: number sourceId?: number
}, },
conditionalPanelLine: null | number conditionalPanelLocation: null | SourceLocation
}; };
export const createUIState = makeRecord( export const createUIState = makeRecord(
@ -53,7 +53,7 @@ export const createUIState = makeRecord(
endPanelCollapsed: prefs.endPanelCollapsed, endPanelCollapsed: prefs.endPanelCollapsed,
frameworkGroupingOn: prefs.frameworkGroupingOn, frameworkGroupingOn: prefs.frameworkGroupingOn,
highlightedLineRange: undefined, highlightedLineRange: undefined,
conditionalPanelLine: null, conditionalPanelLocation: null,
orientation: "horizontal", orientation: "horizontal",
viewport: null viewport: null
}: UIState) }: UIState)
@ -110,10 +110,10 @@ function update(
return state.set("highlightedLineRange", {}); return state.set("highlightedLineRange", {});
case "OPEN_CONDITIONAL_PANEL": case "OPEN_CONDITIONAL_PANEL":
return state.set("conditionalPanelLine", action.line); return state.set("conditionalPanelLocation", action.location);
case "CLOSE_CONDITIONAL_PANEL": case "CLOSE_CONDITIONAL_PANEL":
return state.set("conditionalPanelLine", null); return state.set("conditionalPanelLocation", null);
case "SET_PRIMARY_PANE_TAB": case "SET_PRIMARY_PANE_TAB":
return state.set("selectedPrimaryPaneTab", action.tabName); return state.set("selectedPrimaryPaneTab", action.tabName);
@ -180,8 +180,10 @@ export function getHighlightedLineRange(state: OuterState) {
return state.ui.get("highlightedLineRange"); return state.ui.get("highlightedLineRange");
} }
export function getConditionalPanelLine(state: OuterState): null | number { export function getConditionalPanelLocation(
return state.ui.get("conditionalPanelLine"); state: OuterState
): null | SourceLocation {
return state.ui.get("conditionalPanelLocation");
} }
export function getOrientation(state: OuterState): boolean { export function getOrientation(state: OuterState): boolean {

View File

@ -7,13 +7,12 @@
import { getSymbols } from "../../workers/parser"; import { getSymbols } from "../../workers/parser";
import { findClosestFunction } from "../ast"; import { findClosestFunction } from "../ast";
import type { SymbolDeclarations } from "../../workers/parser";
import type { SourceLocation, Source, ASTLocation } from "../../types"; import type { SourceLocation, Source, ASTLocation } from "../../types";
import type { Symbols } from "../../reducers/ast";
export function getASTLocation( export function getASTLocation(
source: Source, source: Source,
symbols: SymbolDeclarations, symbols: ?Symbols,
location: SourceLocation location: SourceLocation
): ASTLocation { ): ASTLocation {
if (source.isWasm || !symbols || symbols.loading) { if (source.isWasm || !symbols || symbols.loading) {

View File

@ -187,18 +187,9 @@ export function createPendingBreakpoint(bp: Breakpoint) {
} }
export function sortBreakpoints(breakpoints: FormattedBreakpoint[]) { export function sortBreakpoints(breakpoints: FormattedBreakpoint[]) {
breakpoints = breakpoints.map(bp => ({
...bp,
selectedLocation: {
...bp.selectedLocation,
// If a breakpoint has an undefined column, we must provide a 0 value
// or the breakpoint will display after all explicit column numbers
column: bp.selectedLocation.column || 0
}
}));
return sortBy(breakpoints, [ return sortBy(breakpoints, [
"selectedLocation.line", "selectedLocation.line",
"selectedLocation.column" ({ selectedLocation }) =>
selectedLocation.column === undefined || selectedLocation.column
]); ]);
} }

View File

@ -158,17 +158,14 @@ function isVisible(codeMirror: any, top: number, left: number) {
return inXView && inYView; return inXView && inYView;
} }
export function getLocationsInViewport(_editor: any) { export function getLocationsInViewport({ codeMirror }: Object) {
// Get scroll position // Get scroll position
const charWidth = _editor.codeMirror.defaultCharWidth(); const charWidth = codeMirror.defaultCharWidth();
const scrollArea = _editor.codeMirror.getScrollInfo(); const scrollArea = codeMirror.getScrollInfo();
const { scrollLeft } = _editor.codeMirror.doc; const { scrollLeft } = codeMirror.doc;
const rect = _editor.codeMirror.getWrapperElement().getBoundingClientRect(); const rect = codeMirror.getWrapperElement().getBoundingClientRect();
const topVisibleLine = _editor.codeMirror.lineAtHeight(rect.top, "window"); const topVisibleLine = codeMirror.lineAtHeight(rect.top, "window");
const bottomVisibleLine = _editor.codeMirror.lineAtHeight( const bottomVisibleLine = codeMirror.lineAtHeight(rect.bottom, "window");
rect.bottom,
"window"
);
const leftColumn = Math.floor(scrollLeft > 0 ? scrollLeft / charWidth : 0); const leftColumn = Math.floor(scrollLeft > 0 ? scrollLeft / charWidth : 0);
const rightPosition = scrollLeft + (scrollArea.clientWidth - 30); const rightPosition = scrollLeft + (scrollArea.clientWidth - 30);
@ -186,25 +183,29 @@ export function getLocationsInViewport(_editor: any) {
}; };
} }
export function markText(_editor: any, className, { start, end }: EditorRange) { export function markText(
return _editor.codeMirror.markText( { codeMirror }: Object,
className,
{ start, end }: EditorRange
) {
return codeMirror.markText(
{ ch: start.column, line: start.line }, { ch: start.column, line: start.line },
{ ch: end.column, line: end.line }, { ch: end.column, line: end.line },
{ className } { className }
); );
} }
export function lineAtHeight(_editor, sourceId, event) { export function lineAtHeight({ codeMirror }, sourceId, event) {
const _editorLine = _editor.codeMirror.lineAtHeight(event.clientY); const _editorLine = codeMirror.lineAtHeight(event.clientY);
return toSourceLine(sourceId, _editorLine); return toSourceLine(sourceId, _editorLine);
} }
export function getSourceLocationFromMouseEvent( export function getSourceLocationFromMouseEvent(
_editor: Object, { codeMirror }: Object,
selectedLocation: SourceLocation, selectedLocation: SourceLocation,
e: MouseEvent e: MouseEvent
) { ) {
const { line, ch } = _editor.codeMirror.coordsChar({ const { line, ch } = codeMirror.coordsChar({
left: e.clientX, left: e.clientX,
top: e.clientY top: e.clientY
}); });
@ -216,26 +217,30 @@ export function getSourceLocationFromMouseEvent(
}; };
} }
export function forEachLine(codeMirror, iter) { export function forEachLine(codeMirror: Object, iter) {
codeMirror.operation(() => { codeMirror.operation(() => {
codeMirror.doc.iter(0, codeMirror.lineCount(), iter); codeMirror.doc.iter(0, codeMirror.lineCount(), iter);
}); });
} }
export function removeLineClass(codeMirror, line, className) { export function removeLineClass(
codeMirror: Object,
line: number,
className: string
) {
codeMirror.removeLineClass(line, "line", className); codeMirror.removeLineClass(line, "line", className);
} }
export function clearLineClass(codeMirror, className) { export function clearLineClass(codeMirror: Object, className: string) {
forEachLine(codeMirror, line => { forEachLine(codeMirror, line => {
removeLineClass(codeMirror, line, className); removeLineClass(codeMirror, line, className);
}); });
} }
export function getTextForLine(codeMirror, line) { export function getTextForLine(codeMirror: Object, line: number): string {
return codeMirror.getLine(line - 1).trim(); return codeMirror.getLine(line - 1).trim();
} }
export function getCursorLine(codeMirror): number { export function getCursorLine(codeMirror: Object): number {
return codeMirror.getCursor().line; return codeMirror.getCursor().line;
} }

View File

@ -11,7 +11,7 @@ import { getFilename } from "../../source";
// Decodes an anonymous naming scheme that // Decodes an anonymous naming scheme that
// spider monkey implements based on "Naming Anonymous JavaScript Functions" // spider monkey implements based on "Naming Anonymous JavaScript Functions"
// http://johnjbarton.github.io/nonymous/index.html // http://johnjbarton.github.io/nonymous/index.html
const objectProperty = /([\w\d]+)$/; const objectProperty = /([\w\d\$]+)$/;
const arrayProperty = /\[(.*?)\]$/; const arrayProperty = /\[(.*?)\]$/;
const functionProperty = /([\w\d]+)[\/\.<]*?$/; const functionProperty = /([\w\d]+)[\/\.<]*?$/;
const annonymousProperty = /([\w\d]+)\(\^\)$/; const annonymousProperty = /([\w\d]+)\(\^\)$/;

View File

@ -42,15 +42,20 @@ export function formatPausePoints(text: string, pausePoints: PausePoints) {
return lines.join("\n"); return lines.join("\n");
} }
export async function mapPausePoints(pausePoints, iteratee) { export async function mapPausePoints<T>(
pausePoints: PausePoints,
iteratee: PausePoint => T
) {
const results = await Promise.all(convertToList(pausePoints).map(iteratee)); const results = await Promise.all(convertToList(pausePoints).map(iteratee));
const newPausePoints = {};
for (const line in pausePoints) { for (const line in pausePoints) {
const linePoints = pausePoints[line]; const linePoints = pausePoints[line];
const newLinePoints = (newPausePoints[line] = {});
for (const column in linePoints) { for (const column in linePoints) {
linePoints[column] = results.shift(); newLinePoints[column] = results.shift();
} }
} }
return pausePoints; return newPausePoints;
} }

View File

@ -115,7 +115,7 @@ export const features = new PrefsHelper("devtools.debugger.features", {
mapAwaitExpression: ["Bool", "map-await-expression"], mapAwaitExpression: ["Bool", "map-await-expression"],
componentPane: ["Bool", "component-pane"], componentPane: ["Bool", "component-pane"],
xhrBreakpoints: ["Bool", "xhr-breakpoints"], xhrBreakpoints: ["Bool", "xhr-breakpoints"],
originalBlackbox: ["Bool", "origial-blackbox"], originalBlackbox: ["Bool", "origial-blackbox"]
}); });
export const asyncStore = asyncStoreHelper("debugger", { export const asyncStore = asyncStoreHelper("debugger", {

View File

@ -17,7 +17,10 @@ import type { Symbols } from "../reducers/ast";
import type { QuickOpenType } from "../reducers/quick-open"; import type { QuickOpenType } from "../reducers/quick-open";
import type { TabList } from "../reducers/tabs"; import type { TabList } from "../reducers/tabs";
import type { Source } from "../types"; import type { Source } from "../types";
import type { SymbolDeclaration } from "../workers/parser"; import type {
SymbolDeclaration,
IdentifierDeclaration
} from "../workers/parser";
export const MODIFIERS = { export const MODIFIERS = {
"@": "functions", "@": "functions",
@ -86,11 +89,12 @@ export type QuickOpenResult = {|
|}; |};
export type FormattedSymbolDeclarations = {| export type FormattedSymbolDeclarations = {|
variables: Array<QuickOpenResult>,
functions: Array<QuickOpenResult> functions: Array<QuickOpenResult>
|}; |};
export function formatSymbol(symbol: SymbolDeclaration): QuickOpenResult { export function formatSymbol(
symbol: SymbolDeclaration | IdentifierDeclaration
): QuickOpenResult {
return { return {
id: `${symbol.name}:${symbol.location.start.line}`, id: `${symbol.name}:${symbol.location.start.line}`,
title: symbol.name, title: symbol.name,

View File

@ -103,5 +103,6 @@ export type {
ClassDeclaration, ClassDeclaration,
SymbolDeclaration, SymbolDeclaration,
SymbolDeclarations, SymbolDeclarations,
IdentifierDeclaration,
FunctionDeclaration FunctionDeclaration
} from "./getSymbols"; } from "./getSymbols";

View File

@ -1,13 +1,14 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
function findBreakpoint(dbg, url, line) { function findBreakpoint(dbg, url, line, column = 0) {
const { const {
selectors: { getBreakpoint }, selectors: { getBreakpoint },
getState getState
} = dbg; } = dbg;
const source = findSource(dbg, url); const source = findSource(dbg, url);
return getBreakpoint(getState(), { sourceId: source.id, line }); const location = { sourceId: source.id, line, column };
return getBreakpoint(getState(), location);
} }
function getLineEl(dbg, line) { function getLineEl(dbg, line) {
@ -63,6 +64,7 @@ add_task(async function() {
await setConditionalBreakpoint(dbg, 5, "1"); await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "ADD_BREAKPOINT"); await waitForDispatch(dbg, "ADD_BREAKPOINT");
let bp = findBreakpoint(dbg, "simple2", 5); let bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition"); is(bp.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true); assertEditorBreakpoint(dbg, 5, true);

View File

@ -1,6 +1,8 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.importGlobalProperties(["TextEncoder"]);
function gzipCompressString(string, obs) { function gzipCompressString(string, obs) {
let scs = Cc["@mozilla.org/streamConverters;1"] let scs = Cc["@mozilla.org/streamConverters;1"]
@ -71,7 +73,19 @@ function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, status, "DA DA DA"); response.setStatusLine(request.httpVersion, status, "DA DA DA");
response.setHeader("Content-Type", "text/plain", false); response.setHeader("Content-Type", "text/plain", false);
setCacheHeaders(); setCacheHeaders();
response.write("Братан, ты вообще качаешься?");
function convertToUtf8(str) {
return String.fromCharCode(...new TextEncoder().encode(str));
}
// This script must be evaluated as UTF-8 for this to write out the
// bytes of the string in UTF-8. If it's evaluated as Latin-1, the
// written bytes will be the result of UTF-8-encoding this string
// *twice*.
let data = "Братан, ты вообще качаешься?";
let stringOfUtf8Bytes = convertToUtf8(data);
response.write(stringOfUtf8Bytes);
response.finish(); response.finish();
break; break;
} }

View File

@ -67,4 +67,4 @@ pref("devtools.debugger.features.skip-pausing", true);
pref("devtools.debugger.features.autocomplete-expressions", false); pref("devtools.debugger.features.autocomplete-expressions", false);
pref("devtools.debugger.features.map-expression-bindings", true); pref("devtools.debugger.features.map-expression-bindings", true);
pref("devtools.debugger.features.xhr-breakpoints", true); pref("devtools.debugger.features.xhr-breakpoints", true);
pref("devtools.debugger.features.origial-blackbox", false); pref("devtools.debugger.features.origial-blackbox", false);

View File

@ -7133,10 +7133,10 @@ class ObjectInspectorItem extends Component {
onClick: onLabelClick ? event => { onClick: onLabelClick ? event => {
event.stopPropagation(); event.stopPropagation();
// If the user selected text, bail out. const objectProperty = /([\w\d\$]+)$/;
if (Utils.selection.documentHasSelection()) { const arrayProperty = /\[(.*?)\]$/;
return; const functionProperty = /([\w\d]+)[\/\.<]*?$/;
} const annonymousProperty = /([\w\d]+)\(\^\)$/;
onLabelClick(item, { onLabelClick(item, {
depth, depth,
@ -7164,4 +7164,4 @@ module.exports = ObjectInspectorItem;
/***/ }) /***/ })
/******/ }); /******/ });
}); });

View File

@ -9,7 +9,11 @@ const HTML_PART1 =
"<body>" + "<body>" +
"<script id='script' src='"; "<script id='script' src='";
const TESTCASE1 = "http://sub2.ält.example.org/"; // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS, encoded as UTF-8 code units.
// response.write() writes out the provided string characters truncated to
// bytes, so "ä" literally would write a literal \xE4 byte, not the desired
// two-byte UTF-8 sequence.
const TESTCASE1 = "http://sub2.\xC3\xA4lt.example.org/";
const TESTCASE2 = "http://sub2.xn--lt-uia.example.org/" const TESTCASE2 = "http://sub2.xn--lt-uia.example.org/"
const HTML_PART2 = "tests/dom/security/test/csp/file_punycode_host_src.js'></script>" + const HTML_PART2 = "tests/dom/security/test/csp/file_punycode_host_src.js'></script>" +

View File

@ -1,6 +1,9 @@
// SJS file for getAllResponseRequests vs getResponseRequest // SJS file for getAllResponseRequests vs getResponseRequest
function handleRequest(request, response) function handleRequest(request, response)
{ {
response.setHeader("X-Custom-Header-Bytes", "…", false); // Header strings are interpreted by truncating the characters in them to
// bytes, so U+2026 HORIZONTAL ELLIPSIS here must be encoded manually: using
// "…" as the string would write a \x26 byte.
response.setHeader("X-Custom-Header-Bytes", "\xE2\x80\xA6", false);
response.write("42"); response.write("42");
} }

View File

@ -20,7 +20,8 @@ let xhr = new XMLHttpRequest();
xhr.open('GET', 'file_XHR_header.sjs', true); xhr.open('GET', 'file_XHR_header.sjs', true);
xhr.onreadystatechange = function() { xhr.onreadystatechange = function() {
if (xhr.readyState == 4) { if (xhr.readyState == 4) {
ok(xhr.getResponseHeader('X-Custom-Header-Bytes') == "\xE2\x80\xA6", 'getResponseHeader byte-inflates the output'); ok(xhr.getResponseHeader('X-Custom-Header-Bytes') == "\xE2\x80\xA6",
"getResponseHeader returns a string of the header's raw bytes");
SimpleTest.finish(); SimpleTest.finish();
} }
} }

View File

@ -5084,11 +5084,13 @@ void MStoreSlot::printOpcode(GenericPrinter& out) const {
#endif #endif
MDefinition* MFunctionEnvironment::foldsTo(TempAllocator& alloc) { MDefinition* MFunctionEnvironment::foldsTo(TempAllocator& alloc) {
if (!input()->isLambda()) { if (input()->isLambda()) {
return this; return input()->toLambda()->environmentChain();
} }
if (input()->isLambdaArrow()) {
return input()->toLambda()->environmentChain(); return input()->toLambdaArrow()->environmentChain();
}
return this;
} }
static bool AddIsANonZeroAdditionOf(MAdd* add, MDefinition* ins) { static bool AddIsANonZeroAdditionOf(MAdd* add, MDefinition* ins) {

View File

@ -3240,6 +3240,13 @@ void HttpBaseChannel::ReleaseListeners() {
void HttpBaseChannel::DoNotifyListener() { void HttpBaseChannel::DoNotifyListener() {
LOG(("HttpBaseChannel::DoNotifyListener this=%p", this)); LOG(("HttpBaseChannel::DoNotifyListener this=%p", this));
// In case nsHttpChannel::OnStartRequest wasn't called (e.g. due to flag
// LOAD_ONLY_IF_MODIFIED) we want to set mAfterOnStartRequestBegun to true
// before notifying listener.
if (!mAfterOnStartRequestBegun) {
mAfterOnStartRequestBegun = true;
}
if (mListener) { if (mListener) {
MOZ_ASSERT(!mOnStartRequestCalled, MOZ_ASSERT(!mOnStartRequestCalled,
"We should not call OnStartRequest twice"); "We should not call OnStartRequest twice");

View File

@ -2529,7 +2529,7 @@ ServerHandler.prototype =
// separate these two lines! // separate these two lines!
var line = new Error().lineNumber; var line = new Error().lineNumber;
let uri = Services.io.newFileURI(file); let uri = Services.io.newFileURI(file);
Services.scriptloader.loadSubScript(uri.spec, s); Services.scriptloader.loadSubScript(uri.spec, s, "UTF-8");
} catch (e) { } catch (e) {
dumpn("*** syntax error in SJS at " + file.path + ": " + e); dumpn("*** syntax error in SJS at " + file.path + ": " + e);
throw HTTP_500; throw HTTP_500;

View File

@ -2,12 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use style;
#[cfg(all(test, target_pointer_width = "64"))] #[cfg(all(test, target_pointer_width = "64"))]
#[test] #[test]
fn size_of_specified_values() { fn size_of_specified_values() {
use style;
use std::mem::size_of; use std::mem::size_of;
let threshold = 24; let threshold = 24;
let mut bad_properties = vec![]; let mut bad_properties = vec![];

View File

@ -4,6 +4,8 @@
Cu.import("resource://gre/modules/Timer.jsm"); Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.importGlobalProperties(["TextEncoder"]);
/** /**
* Provide search suggestions in the OpenSearch JSON format. * Provide search suggestions in the OpenSearch JSON format.
*/ */
@ -12,10 +14,21 @@ function handleRequest(request, response) {
// Get the query parameters from the query string. // Get the query parameters from the query string.
let query = parseQueryString(request.queryString); let query = parseQueryString(request.queryString);
function convertToUtf8(str) {
return String.fromCharCode(...new TextEncoder().encode(str));
}
function writeSuggestions(query, completions = []) { function writeSuggestions(query, completions = []) {
let result = [query, completions]; let result = [query, completions];
response.write(JSON.stringify(result)); let jsonString = JSON.stringify([query, completions]);
return result;
// This script must be evaluated as UTF-8 for this to write out the bytes of
// the string in UTF-8. If it's evaluated as Latin-1, the written bytes
// will be the result of UTF-8-encoding the result-string *twice*, which
// will break the "I ❤️" case further down.
let stringOfUtf8Bytes = convertToUtf8(jsonString);
response.write(stringOfUtf8Bytes);
} }
response.setStatusLine(request.httpVersion, 200, "OK"); response.setStatusLine(request.httpVersion, 200, "OK");
@ -73,7 +86,7 @@ function parseQueryString(queryString) {
let query = {}; let query = {};
queryString.split('&').forEach(function (val) { queryString.split('&').forEach(function (val) {
let [name, value] = val.split('='); let [name, value] = val.split('=');
query[name] = unescape(value).replace(/[+]/g, " "); query[name] = decodeURIComponent(value).replace(/[+]/g, " ");
}); });
return query; return query;
} }

View File

@ -19,7 +19,7 @@
} }
#header-utils-btn > .toolbarbutton-menu-dropmarker { #header-utils-btn > .toolbarbutton-menu-dropmarker {
list-style-image: url("chrome://mozapps/skin/extensions/toolbarbutton-dropmarker.png"); list-style-image: url("chrome://global/skin/icons/arrow-dropdown-12.svg");
padding: 0; padding: 0;
margin-inline-start: 2px; margin-inline-start: 2px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

View File

@ -10,7 +10,6 @@ toolkit.jar:
skin/classic/mozapps/extensions/rating-won.png (extensions/rating-won.png) skin/classic/mozapps/extensions/rating-won.png (extensions/rating-won.png)
skin/classic/mozapps/extensions/rating-not-won.png (extensions/rating-not-won.png) skin/classic/mozapps/extensions/rating-not-won.png (extensions/rating-not-won.png)
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png) skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/mozapps/extensions/toolbarbutton-dropmarker.png (extensions/toolbarbutton-dropmarker.png)
* skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css) * skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css) skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)
skin/classic/mozapps/profile/profileSelection.css (profile/profileSelection.css) skin/classic/mozapps/profile/profileSelection.css (profile/profileSelection.css)

View File

@ -13,6 +13,7 @@
#include "mozilla/Result.h" #include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h" #include "mozilla/ResultExtensions.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/SimpleEnumerator.h" #include "mozilla/SimpleEnumerator.h"
#include "mozilla/SystemGroup.h" #include "mozilla/SystemGroup.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
@ -228,6 +229,12 @@ static inline void HandleMemoryReport(Telemetry::HistogramID aId,
nsresult MemoryTelemetry::GatherReports( nsresult MemoryTelemetry::GatherReports(
const std::function<void()>& aCompletionCallback) { const std::function<void()>& aCompletionCallback) {
auto cleanup = MakeScopeExit([&]() {
if (aCompletionCallback) {
aCompletionCallback();
}
});
RefPtr<nsMemoryReporterManager> mgr = nsMemoryReporterManager::GetOrCreate(); RefPtr<nsMemoryReporterManager> mgr = nsMemoryReporterManager::GetOrCreate();
MOZ_DIAGNOSTIC_ASSERT(mgr); MOZ_DIAGNOSTIC_ASSERT(mgr);
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
@ -315,7 +322,9 @@ nsresult MemoryTelemetry::GatherReports(
#undef RECORD #undef RECORD
nsresult rv = mThreadPool->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL); nsresult rv = mThreadPool->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
Unused << NS_WARN_IF(NS_FAILED(rv)); if (!NS_WARN_IF(NS_FAILED(rv))) {
cleanup.release();
}
// If we're running in the parent process, collect data from all processes for // If we're running in the parent process, collect data from all processes for
// the MEMORY_TOTAL histogram. // the MEMORY_TOTAL histogram.