Bug 1523386 - [release 121] Distinguish between condition and log value in breakpoints (#7749). r=dwalsh

This commit is contained in:
Brian Hackett 2019-01-28 14:59:30 -05:00 committed by Jason Laster
parent 6ba3f76565
commit 5f0bf41d9d
27 changed files with 209 additions and 153 deletions

View File

@ -20,9 +20,12 @@ import { getGeneratedLocation } from "../../utils/source-maps";
import { getTextAtPosition } from "../../utils/source";
import { recordEvent } from "../../utils/telemetry";
import type { SourceLocation, Breakpoint } from "../../types";
import type {
BreakpointOptions,
Breakpoint,
SourceLocation
} from "../../types";
import type { ThunkArgs } from "../types";
import type { addBreakpointOptions } from "./";
async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
const state = getState();
@ -58,7 +61,7 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
const { id, actualLocation } = await client.setBreakpoint(
generatedLocation,
breakpoint.condition,
breakpoint.options,
isOriginalId(location.sourceId)
);
@ -76,10 +79,8 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
const newBreakpoint = {
id,
disabled: false,
hidden: breakpoint.hidden,
loading: false,
condition: breakpoint.condition,
log: breakpoint.log,
options: breakpoint.options,
location: newLocation,
astLocation,
generatedLocation: newGeneratedLocation,
@ -122,14 +123,22 @@ export function enableBreakpoint(breakpoint: Breakpoint) {
};
}
/**
* Add a new breakpoint
*
* @memberof actions/breakpoints
* @static
* @param {BreakpointOptions} options Any options for the new breakpoint.
*/
export function addBreakpoint(
location: SourceLocation,
{ condition, hidden, log = false }: addBreakpointOptions = {}
options: BreakpointOptions = {}
) {
return ({ dispatch, getState, sourceMaps, client }: ThunkArgs) => {
recordEvent("add_breakpoint");
const breakpoint = createBreakpoint(location, { condition, hidden, log });
const breakpoint = createBreakpoint(location, options);
return dispatch({
type: "ADD_BREAKPOINT",

View File

@ -36,6 +36,7 @@ import { isEmptyLineInSource } from "../../reducers/ast";
import type { ThunkArgs, Action } from "../types";
import type {
Breakpoint,
BreakpointOptions,
Source,
SourceLocation,
XHRBreakpoint
@ -43,12 +44,6 @@ import type {
import { recordEvent } from "../../utils/telemetry";
export type addBreakpointOptions = {
condition?: string,
hidden?: boolean,
log?: boolean
};
/**
* Remove a single breakpoint
*
@ -260,25 +255,24 @@ export function remapBreakpoints(sourceId: string) {
}
/**
* Update the condition of a breakpoint.
* Update the options of a breakpoint.
*
* @throws {Error} "not implemented"
* @memberof actions/breakpoints
* @static
* @param {SourceLocation} location
* @see DebuggerController.Breakpoints.addBreakpoint
* @param {string} condition
* The condition to set on the breakpoint
* @param {Boolean} $1.disabled Disable value for breakpoint value
* @param {Object} options
* Any options to set on the breakpoint
*/
export function setBreakpointCondition(
export function setBreakpointOptions(
location: SourceLocation,
{ condition, log = false }: addBreakpointOptions = {}
options: BreakpointOptions = {}
) {
return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
const bp = getBreakpoint(getState(), location);
if (!bp) {
return dispatch(addBreakpoint(location, { condition, log }));
return dispatch(addBreakpoint(location, options));
}
if (bp.loading) {
@ -289,20 +283,20 @@ export function setBreakpointCondition(
await dispatch(enableBreakpoint(bp));
}
await client.setBreakpointCondition(
await client.setBreakpointOptions(
bp.id,
location,
condition,
options,
isOriginalId(bp.location.sourceId)
);
const newBreakpoint = { ...bp, disabled: false, condition, log };
const newBreakpoint = { ...bp, disabled: false, options };
assertBreakpoint(newBreakpoint);
return dispatch(
({
type: "SET_BREAKPOINT_CONDITION",
type: "SET_BREAKPOINT_OPTIONS",
breakpoint: newBreakpoint
}: Action)
);

View File

@ -157,8 +157,8 @@ export async function syncBreakpointPromise(
const { id, actualLocation } = await client.setBreakpoint(
scopedGeneratedLocation,
pendingBreakpoint.condition,
isOriginalId(sourceId)
isOriginalId(sourceId),
pendingBreakpoint.options
);
// the breakpoint might have slid server side, so we want to get the location

View File

@ -11,14 +11,12 @@ Object {
"sourceUrl": "http://localhost:8000/examples/a",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"line": 7,
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"hidden": false,
"id": "a:5:",
"loading": false,
"location": Object {
@ -26,7 +24,11 @@ Object {
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
}
@ -46,14 +48,12 @@ Array [
"sourceUrl": "http://localhost:8000/examples/a",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"line": 2,
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"hidden": false,
"id": "hi",
"loading": false,
"location": Object {
@ -61,7 +61,11 @@ Array [
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "return a",
"text": "return a",
},
@ -97,14 +101,12 @@ Object {
"sourceUrl": "http://localhost:8000/examples/a.js",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"line": 1,
"sourceId": "a.js",
"sourceUrl": "http://localhost:8000/examples/a.js",
},
"hidden": false,
"id": "hi",
"loading": false,
"location": Object {
@ -113,7 +115,11 @@ Object {
"sourceId": "a.js/originalSource-d6d70368d5c252598541e693a7ad6c27",
"sourceUrl": "http://localhost:8000/examples/a.js:formatted",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "function a() {",
"text": "function a() {",
}
@ -133,14 +139,12 @@ Array [
"sourceUrl": "http://localhost:8000/examples/a",
},
},
"condition": null,
"disabled": true,
"generatedLocation": Object {
"line": 5,
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"hidden": false,
"id": "hi",
"loading": false,
"location": Object {
@ -148,7 +152,11 @@ Array [
"sourceId": "a",
"sourceUrl": "http://localhost:8000/examples/a",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
},

View File

@ -9,7 +9,6 @@ Object {
"line": 3,
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -17,7 +16,6 @@ Object {
"sourceId": "gen.js",
"sourceUrl": "http://localhost:8000/gen.js",
},
"hidden": false,
"id": "foo",
"loading": false,
"location": Object {
@ -26,7 +24,11 @@ Object {
"sourceId": "magic.js",
"sourceUrl": "http://localhost:8000/examples/magic.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
},
@ -48,7 +50,6 @@ Object {
"line": 3,
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -56,7 +57,6 @@ Object {
"sourceId": "gen.js",
"sourceUrl": "http://localhost:8000/gen.js",
},
"hidden": false,
"id": "foo",
"loading": false,
"location": Object {
@ -65,7 +65,11 @@ Object {
"sourceId": "magic.js",
"sourceUrl": "http://localhost:8000/examples/magic.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
},
@ -87,7 +91,6 @@ Object {
"line": 3,
},
},
"condition": null,
"disabled": true,
"generatedLocation": Object {
"column": undefined,
@ -99,7 +102,11 @@ Object {
"line": 3,
"sourceUrl": "http://localhost:8000/examples/magic.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
},
}
`;
@ -113,7 +120,6 @@ Object {
"line": 3,
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -121,7 +127,6 @@ Object {
"sourceId": "gen.js",
"sourceUrl": "http://localhost:8000/gen.js",
},
"hidden": false,
"id": "foo",
"loading": false,
"location": Object {
@ -130,7 +135,11 @@ Object {
"sourceId": "magic.js",
"sourceUrl": "http://localhost:8000/examples/magic.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
},
@ -152,7 +161,6 @@ Object {
"line": 3,
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -160,7 +168,6 @@ Object {
"sourceId": "gen.js",
"sourceUrl": "http://localhost:8000/gen.js",
},
"hidden": false,
"id": "gen.js:5:",
"loading": false,
"location": Object {
@ -169,7 +176,11 @@ Object {
"sourceId": "magic.js",
"sourceUrl": "http://localhost:8000/magic.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
"originalText": "",
"text": "",
},

View File

@ -281,16 +281,18 @@ describe("breakpoints", () => {
await dispatch(actions.addBreakpoint(loc));
expect(selectors.getBreakpoint(getState(), loc).condition).toBe(null);
expect(selectors.getBreakpoint(getState(), loc).options.condition).toBe(
null
);
await dispatch(
actions.setBreakpointCondition(loc, {
actions.setBreakpointOptions(loc, {
condition: "const foo = 0",
getTextForLine: () => {}
})
);
expect(selectors.getBreakpoint(getState(), loc).condition).toBe(
expect(selectors.getBreakpoint(getState(), loc).options.condition).toBe(
"const foo = 0"
);
});
@ -308,17 +310,19 @@ describe("breakpoints", () => {
const { breakpoint } = await dispatch(actions.addBreakpoint(loc));
await dispatch(actions.disableBreakpoint(breakpoint));
expect(selectors.getBreakpoint(getState(), loc).condition).toBe(null);
expect(selectors.getBreakpoint(getState(), loc).options.condition).toBe(
null
);
await dispatch(
actions.setBreakpointCondition(loc, {
actions.setBreakpointOptions(loc, {
condition: "const foo = 0",
getTextForLine: () => {}
})
);
const newBreakpoint = selectors.getBreakpoint(getState(), loc);
expect(newBreakpoint.disabled).toBe(false);
expect(newBreakpoint.condition).toBe("const foo = 0");
expect(newBreakpoint.options.condition).toBe("const foo = 0");
});
it("should remap breakpoints on pretty print", async () => {

View File

@ -38,7 +38,6 @@ Object {
"sourceUrl": "http://localhost:8000/examples/foo.js",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -50,7 +49,11 @@ Object {
"line": 7,
"sourceUrl": "http://localhost:8000/examples/foo.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
}
`;
@ -65,7 +68,6 @@ Object {
"sourceUrl": "http://localhost:8000/examples/foo.js",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -77,7 +79,11 @@ Object {
"line": 5,
"sourceUrl": "http://localhost:8000/examples/foo.js",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
}
`;
@ -92,7 +98,6 @@ Object {
"sourceUrl": "http://localhost:8000/examples/foo",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -104,7 +109,11 @@ Object {
"line": 5,
"sourceUrl": "http://localhost:8000/examples/foo",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
}
`;
@ -119,7 +128,6 @@ Object {
"sourceUrl": "http://localhost:8000/examples/foo2",
},
},
"condition": null,
"disabled": false,
"generatedLocation": Object {
"column": undefined,
@ -131,6 +139,10 @@ Object {
"line": 5,
"sourceUrl": "http://localhost:8000/examples/foo2",
},
"log": false,
"options": Object {
"condition": null,
"hidden": false,
"logValue": null,
},
}
`;

View File

@ -42,8 +42,10 @@ export function generateBreakpoint(filename, line = 5, column) {
line,
column
},
condition: null,
disabled: false,
hidden: false
options: {
condition: null,
hidden: false
},
disabled: false
};
}

View File

@ -37,7 +37,7 @@ export const simpleMockThreadClient = {
removeBreakpoint: _id => Promise.resolve(),
setBreakpointCondition: (_id, _location, _condition, _noSliding) =>
setBreakpointOptions: (_id, _location, _options, _noSliding) =>
Promise.resolve({ sourceId: "a", line: 5 }),
setPausePoints: () => Promise.resolve({}),
sourceContents: sourceId =>

View File

@ -152,11 +152,11 @@ describe("when changing an existing breakpoint", () => {
await dispatch(actions.addBreakpoint(bp.location));
await dispatch(
actions.setBreakpointCondition(bp.location, { condition: "2" })
actions.setBreakpointOptions(bp.location, { condition: "2" })
);
const bps = selectors.getPendingBreakpoints(getState());
const breakpoint = bps[id];
expect(breakpoint.condition).toBe("2");
expect(breakpoint.options.condition).toBe("2");
});
it("if disabled, updates corresponding pendingBreakpoint", async () => {
@ -191,11 +191,11 @@ describe("when changing an existing breakpoint", () => {
await dispatch(actions.addBreakpoint(bp.location));
await dispatch(
actions.setBreakpointCondition(bp.location, { condition: "2" })
actions.setBreakpointOptions(bp.location, { condition: "2" })
);
const bps = selectors.getPendingBreakpoints(getState());
const breakpoint = bps[id];
expect(breakpoint.condition).toBe("2");
expect(breakpoint.options.condition).toBe("2");
});
});

View File

@ -57,7 +57,7 @@ export type BreakpointAction =
+status: "done"
|}
| {|
+type: "SET_BREAKPOINT_CONDITION",
+type: "SET_BREAKPOINT_OPTIONS",
+breakpoint: Breakpoint
|}
| PromiseAction<{|

View File

@ -6,6 +6,7 @@
import type {
BreakpointId,
BreakpointOptions,
BreakpointResult,
EventListenerBreakpoints,
Frame,
@ -159,10 +160,10 @@ function getBreakpointByLocation(location: SourceLocation) {
const bpClient = bpClients[id];
if (bpClient) {
const { actor, url, line, column, condition } = bpClient.location;
const { actor, url, line, column } = bpClient.location;
return {
id: bpClient.actor,
condition,
options: bpClient.options,
actualLocation: {
line,
column,
@ -182,9 +183,18 @@ function removeXHRBreakpoint(path: string, method: string) {
return threadClient.removeXHRBreakpoint(path, method);
}
// Source and breakpoint clients do not yet support an options structure, so
// for now we transform options into condition strings when setting breakpoints.
function transformOptionsToCondition(options) {
if (options.logValue) {
return `console.log(${options.logValue})`;
}
return options.condition;
}
function setBreakpoint(
location: SourceLocation,
condition: boolean,
options: BreakpointOptions,
noSliding: boolean
): Promise<BreakpointResult> {
const sourceThreadClient = sourceThreads[location.sourceId];
@ -194,7 +204,7 @@ function setBreakpoint(
.setBreakpoint({
line: location.line,
column: location.column,
condition,
condition: transformOptionsToCondition(options),
noSliding
})
.then(([{ actualLocation }, bpClient]) => {
@ -226,18 +236,17 @@ function removeBreakpoint(
}
}
function setBreakpointCondition(
function setBreakpointOptions(
breakpointId: BreakpointId,
location: SourceLocation,
condition: boolean,
noSliding: boolean
options: BreakpointOptions
) {
const bpClient = bpClients[breakpointId];
delete bpClients[breakpointId];
const sourceThreadClient = sourceThreads[bpClient.source.actor];
return bpClient
.setCondition(sourceThreadClient, condition, noSliding)
.setCondition(sourceThreadClient, transformOptionsToCondition(options))
.then(_bpClient => {
bpClients[breakpointId] = _bpClient;
return { id: breakpointId };
@ -470,7 +479,7 @@ const clientCommands = {
setXHRBreakpoint,
removeXHRBreakpoint,
removeBreakpoint,
setBreakpointCondition,
setBreakpointOptions,
evaluate,
evaluateInFrame,
evaluateExpressions,

View File

@ -11,6 +11,7 @@
*/
import type {
BreakpointOptions,
FrameId,
ActorId,
Script,
@ -387,14 +388,12 @@ export type BreakpointClient = {
actor: string,
url: string,
line: number,
column: ?number,
condition: string
column: ?number
},
setCondition: (ThreadClient, boolean, boolean) => Promise<BreakpointClient>,
// getCondition: () => any,
// hasCondition: () => any,
setCondition: (ThreadClient, ?string) => Promise<BreakpointClient>,
// request: any,
source: SourceClient
source: SourceClient,
options: BreakpointOptions
};
export type BPClients = { [id: ActorId]: BreakpointClient };

View File

@ -116,7 +116,7 @@ class Breakpoint extends PureComponent<Props> {
const { breakpoint, editor, selectedSource } = this.props;
// Hidden Breakpoints are never rendered on the client
if (breakpoint.hidden) {
if (breakpoint.options.hidden) {
return;
}
@ -133,12 +133,10 @@ class Breakpoint extends PureComponent<Props> {
doc.setGutterMarker(line, "breakpoints", this.makeMarker());
editor.codeMirror.addLineClass(line, "line", "new-breakpoint");
if (breakpoint.condition) {
if (breakpoint.log) {
editor.codeMirror.addLineClass(line, "line", "has-condition log");
} else {
editor.codeMirror.addLineClass(line, "line", "has-condition");
}
if (breakpoint.options.condition) {
editor.codeMirror.addLineClass(line, "line", "has-condition");
} else if (breakpoint.options.logValue) {
editor.codeMirror.addLineClass(line, "line", "has-condition log");
} else {
editor.codeMirror.removeLineClass(line, "line", "has-condition");
}

View File

@ -32,7 +32,7 @@ ReactDOM.render(<Svg name={"column-marker"} />, breakpointImg);
function makeBookmark({ breakpoint }, { onClick, onContextMenu }) {
const bp = breakpointImg.cloneNode(true);
const condition = breakpoint && breakpoint.condition;
const condition = breakpoint && breakpoint.options.condition;
const isActive = breakpoint && !breakpoint.disabled;
bp.className = classnames("column-breakpoint", {

View File

@ -21,7 +21,7 @@ import type { SourceLocation } from "../../types";
type Props = {
breakpoint: ?Object,
setBreakpointCondition: Function,
setBreakpointOptions: Function,
location: SourceLocation,
log: boolean,
editor: Object,
@ -64,10 +64,10 @@ export class ConditionalPanel extends PureComponent<Props> {
setBreakpoint(condition: string) {
const { location, log } = this.props;
if (log) {
condition = `console.log(${condition})`;
}
return this.props.setBreakpointCondition(location, { condition, log });
return this.props.setBreakpointOptions(
location,
log ? { logValue: condition } : { condition }
);
}
clearConditionalPanel() {
@ -144,13 +144,8 @@ export class ConditionalPanel extends PureComponent<Props> {
renderConditionalPanel(props: Props) {
const { breakpoint, log } = props;
let condition = breakpoint ? breakpoint.condition : "";
if (log) {
if (condition && condition.match(/^console.log\(.*\)$/)) {
condition = condition.match(/^console.log\((.*)\)/)[1];
}
}
const options = (breakpoint && breakpoint.options) || {};
const condition = log ? options.logValue : options.condition;
const panel = document.createElement("div");
ReactDOM.render(
@ -198,13 +193,13 @@ const mapStateToProps = state => {
};
const {
setBreakpointCondition,
setBreakpointOptions,
openConditionalPanel,
closeConditionalPanel
} = actions;
const mapDispatchToProps = {
setBreakpointCondition,
setBreakpointOptions,
openConditionalPanel,
closeConditionalPanel
};

View File

@ -85,7 +85,10 @@ export const conditionalBreakpointItem = (
breakpoint: Breakpoint,
breakpointActions: BreakpointItemActions
) => {
const { condition, location } = breakpoint;
const {
options: { condition },
location
} = breakpoint;
return condition
? editConditionalBreakpointItem(location, breakpointActions)
: addConditionalBreakpointItem(location, breakpointActions);
@ -119,7 +122,10 @@ export const logPointItem = (
breakpoint: Breakpoint,
breakpointActions: BreakpointItemActions
) => {
const { condition, location } = breakpoint;
const {
options: { condition },
location
} = breakpoint;
return condition
? editLogPointItem(location, breakpointActions)
: addLogPointItem(location, breakpointActions);

View File

@ -50,7 +50,7 @@ type Props = {
removeBreakpoints: typeof actions.removeBreakpoints,
removeAllBreakpoints: typeof actions.removeAllBreakpoints,
disableBreakpoint: typeof actions.disableBreakpoint,
setBreakpointCondition: typeof actions.setBreakpointCondition,
setBreakpointOptions: typeof actions.setBreakpointOptions,
toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
toggleBreakpoints: typeof actions.toggleBreakpoints,
toggleDisabledBreakpoint: typeof actions.toggleDisabledBreakpoint,
@ -70,7 +70,7 @@ class Breakpoint extends PureComponent<Props> {
onDoubleClick = () => {
const { breakpoint, openConditionalPanel } = this.props;
if (breakpoint.condition) {
if (breakpoint.options.condition) {
openConditionalPanel(this.selectedLocation);
}
};
@ -122,7 +122,10 @@ class Breakpoint extends PureComponent<Props> {
getBreakpointText() {
const { breakpoint, selectedSource } = this.props;
return breakpoint.condition || getSelectedText(breakpoint, selectedSource);
return (
breakpoint.options.condition ||
getSelectedText(breakpoint, selectedSource)
);
}
highlightText = memoize(
@ -150,8 +153,8 @@ class Breakpoint extends PureComponent<Props> {
breakpoint,
paused: this.isCurrentlyPausedAtBreakpoint(),
disabled: breakpoint.disabled,
"is-conditional": !!breakpoint.condition,
log: breakpoint.log
"is-conditional": !!breakpoint.options.condition,
log: !!breakpoint.options.logValue
})}
onClick={this.selectBreakpoint}
onDoubleClick={this.onDoubleClick}
@ -214,7 +217,7 @@ export default connect(
removeAllBreakpoints: actions.removeAllBreakpoints,
disableBreakpoint: actions.disableBreakpoint,
selectSpecificLocation: actions.selectSpecificLocation,
setBreakpointCondition: actions.setBreakpointCondition,
setBreakpointOptions: actions.setBreakpointOptions,
toggleAllBreakpoints: actions.toggleAllBreakpoints,
toggleBreakpoints: actions.toggleBreakpoints,
toggleDisabledBreakpoint: actions.toggleDisabledBreakpoint,

View File

@ -20,7 +20,7 @@ type Props = {
toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
toggleDisabledBreakpoint: typeof actions.toggleDisabledBreakpoint,
selectSpecificLocation: typeof actions.selectSpecificLocation,
setBreakpointCondition: typeof actions.setBreakpointCondition,
setBreakpointOptions: typeof actions.setBreakpointOptions,
openConditionalPanel: typeof actions.openConditionalPanel,
contextMenuEvent: SyntheticEvent<HTMLElement>
};
@ -37,7 +37,7 @@ export default function showContextMenu(props: Props) {
toggleAllBreakpoints,
toggleDisabledBreakpoint,
selectSpecificLocation,
setBreakpointCondition,
setBreakpointOptions,
openConditionalPanel,
contextMenuEvent
} = props;
@ -189,7 +189,7 @@ export default function showContextMenu(props: Props) {
label: removeConditionLabel,
accesskey: removeConditionKey,
disabled: false,
click: () => setBreakpointCondition(selectedLocation)
click: () => setBreakpointOptions(selectedLocation, {})
};
const addConditionItem = {
@ -245,15 +245,15 @@ export default function showContextMenu(props: Props) {
},
{
item: addConditionItem,
hidden: () => breakpoint.condition
hidden: () => breakpoint.options.condition
},
{
item: editConditionItem,
hidden: () => !breakpoint.condition
hidden: () => !breakpoint.options.condition
},
{
item: removeConditionItem,
hidden: () => !breakpoint.condition
hidden: () => !breakpoint.options.condition
}
];

View File

@ -32,7 +32,7 @@ describe("Breakpoint", () => {
const { component } = render({
selectedSource: makeOriginalSource("foo"),
frame: { selectedLocation: location },
breakpoint: { location }
breakpoint: { location, options: {} }
});
expect(component).toMatchSnapshot();
@ -63,6 +63,7 @@ function makeBreakpoint(overrides = {}) {
location,
generatedLocation,
disabled: false,
options: {},
...overrides
};
}

View File

@ -64,7 +64,7 @@ function update(
return updateAllBreakpoints(state, action);
}
case "SET_BREAKPOINT_CONDITION": {
case "SET_BREAKPOINT_OPTIONS": {
return updateBreakpoint(state, action);
}
@ -323,7 +323,7 @@ export function getBreakpointForLocation(
export function getHiddenBreakpoint(state: OuterState): ?Breakpoint {
const breakpoints = getBreakpointsList(state);
return breakpoints.find(bp => bp.hidden);
return breakpoints.find(bp => bp.options.hidden);
}
export default update;

View File

@ -49,12 +49,12 @@ function update(state: PendingBreakpointsState = {}, action: Action) {
return updateAllBreakpoints(state, action);
}
case "SET_BREAKPOINT_CONDITION": {
case "SET_BREAKPOINT_OPTIONS": {
return updateBreakpoint(state, action);
}
case "REMOVE_BREAKPOINT": {
if (action.breakpoint.hidden) {
if (action.breakpoint.options.hidden) {
return state;
}
return removeBreakpoint(state, action);
@ -65,7 +65,7 @@ function update(state: PendingBreakpointsState = {}, action: Action) {
}
function addBreakpoint(state, action) {
if (action.breakpoint.hidden || action.status !== "done") {
if (action.breakpoint.options.hidden || action.status !== "done") {
return state;
}
// when the action completes, we can commit the breakpoint

View File

@ -31,9 +31,9 @@ function getBreakpointsForSource(
.sort((a, b) => a.location.line - b.location.line)
.filter(
bp =>
!bp.hidden &&
!bp.options.hidden &&
!bp.loading &&
(bp.text || bp.originalText || bp.condition || bp.disabled)
(bp.text || bp.originalText || bp.options.condition || bp.disabled)
)
.filter(
bp => getSelectedLocation(bp, selectedSource).sourceId == source.id

View File

@ -101,13 +101,17 @@ export type Breakpoint = {|
+generatedLocation: SourceLocation,
+loading: boolean,
+disabled: boolean,
+hidden: boolean,
+text: string,
+originalText: string,
+condition: ?string,
+log: boolean
+options: BreakpointOptions
|};
export type BreakpointOptions = {
hidden?: boolean,
condition?: string,
logValue?: string
};
/**
* XHR Breakpoint
* @memberof types
@ -145,7 +149,7 @@ export type PendingBreakpoint = {
+loading: boolean,
+disabled: boolean,
+text: string,
+condition: ?string
+options: BreakpointOptions
};
/**

View File

@ -134,7 +134,7 @@ export function createBreakpoint(
id,
text,
originalText,
log
logValue
} = overrides;
const defaultASTLocation = {
@ -144,10 +144,12 @@ export function createBreakpoint(
};
const properties = {
id,
condition: condition || null,
log: log || false,
options: {
condition: condition || null,
logValue: logValue || null,
hidden: hidden || false
},
disabled: disabled || false,
hidden: hidden || false,
loading: false,
astLocation: astLocation || defaultASTLocation,
generatedLocation: generatedLocation || location,
@ -187,8 +189,7 @@ export function createPendingBreakpoint(bp: Breakpoint) {
assertPendingLocation(pendingLocation);
return {
condition: bp.condition,
log: bp.log,
options: bp.options,
disabled: bp.disabled,
location: pendingLocation,
astLocation: bp.astLocation,

View File

@ -9,7 +9,7 @@ import { isDevelopment } from "devtools-environment";
import Services from "devtools-services";
import { asyncStoreHelper } from "./asyncStoreHelper";
const prefsSchemaVersion = "1.0.5";
const prefsSchemaVersion = "1.0.6";
const pref = Services.pref;

View File

@ -68,14 +68,14 @@ add_task(async function() {
await waitForDispatch(dbg, "ADD_BREAKPOINT");
let bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition");
is(bp.options.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true);
// Edit the conditional breakpoint set above
await setConditionalBreakpoint(dbg, 5, "2");
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
await waitForDispatch(dbg, "SET_BREAKPOINT_OPTIONS");
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "12", "breakpoint is created with the condition");
is(bp.options.condition, "12", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true);
clickElement(dbg, "gutter", 5);
@ -88,18 +88,18 @@ add_task(async function() {
clickElement(dbg, "gutter", 5);
await waitForDispatch(dbg, "ADD_BREAKPOINT");
await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
await waitForDispatch(dbg, "SET_BREAKPOINT_OPTIONS");
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition");
is(bp.options.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true);
const bpCondition = waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
const bpCondition = waitForDispatch(dbg, "SET_BREAKPOINT_OPTIONS");
//right click breakpoint in breakpoints list
rightClickElement(dbg, "breakpointItem", 3)
// select "remove condition";
selectContextMenuItem(dbg, selectors.breakpointContextMenu.removeCondition);
await bpCondition;
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, undefined, "breakpoint condition removed");
is(bp.options.condition, undefined, "breakpoint condition removed");
});