mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Merge inbound to mozilla-central a=merge
This commit is contained in:
commit
bbc7fc4e7c
@ -558,8 +558,8 @@ class SearchOneOffs {
|
||||
// Make the top-level menu button.
|
||||
let button = document.createXULElement("toolbarbutton");
|
||||
list.appendChild(button);
|
||||
button.classList.add("addengine-item", "badged-button");
|
||||
button.setAttribute("class", "addengine-menu-button");
|
||||
button.classList.add("addengine-menu-button", "addengine-item",
|
||||
"badged-button");
|
||||
button.setAttribute("type", "menu");
|
||||
button.setAttribute("label",
|
||||
this.bundle.GetStringFromName("cmd_addFoundEngineMenu"));
|
||||
|
@ -1,9 +1,9 @@
|
||||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 110
|
||||
Version 111
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-109...release-110
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-110...release-111
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
12
devtools/client/debugger/new/dist/debugger.css
vendored
12
devtools/client/debugger/new/dist/debugger.css
vendored
@ -1787,8 +1787,8 @@ html .toggle-button.end.vertical svg {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.sources-list .tree .focused img:not(.vue):not(.angular),
|
||||
.sources-list .managed-tree .tree .node.focused img.blackBox {
|
||||
.sources-list .tree .focused .img:not(.vue):not(.angular),
|
||||
.sources-list .managed-tree .tree .node.focused .img.blackBox {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
@ -1919,10 +1919,6 @@ html .toggle-button.end.vertical svg {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.theme-dark .sources-list .managed-tree .tree .node:not(.focused) .img.blackBox {
|
||||
background-color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.theme-dark .sources-list .managed-tree .tree .node .img.blackBox {
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
@ -3700,6 +3696,10 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
||||
.worker-list .worker:hover {
|
||||
background-color: var(--search-overlays-semitransparent);
|
||||
}
|
||||
|
||||
.worker-list .worker.selected {
|
||||
background-color: var(--tab-line-selected-color);
|
||||
}
|
||||
/* 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/>. */
|
||||
|
@ -1015,6 +1015,9 @@ exports.getMemberExpression = getMemberExpression;
|
||||
exports.getVariables = getVariables;
|
||||
exports.getPatternIdentifiers = getPatternIdentifiers;
|
||||
exports.isTopLevel = isTopLevel;
|
||||
exports.nodeHasSameLocation = nodeHasSameLocation;
|
||||
exports.sameLocation = sameLocation;
|
||||
exports.getFunctionParameterNames = getFunctionParameterNames;
|
||||
|
||||
var _types = __webpack_require__(2268);
|
||||
|
||||
@ -1057,7 +1060,7 @@ function getObjectExpressionValue(node) {
|
||||
return value.name;
|
||||
}
|
||||
|
||||
if (t.isCallExpression(value)) {
|
||||
if (t.isCallExpression(value) || t.isFunctionExpression(value)) {
|
||||
return "";
|
||||
}
|
||||
const code = (0, _generator2.default)(value).code;
|
||||
@ -1178,6 +1181,38 @@ function isTopLevel(ancestors) {
|
||||
return ancestors.filter(ancestor => ancestor.key == "body").length == 1;
|
||||
}
|
||||
|
||||
function nodeHasSameLocation(a, b) {
|
||||
return sameLocation(a.location, b.location);
|
||||
}
|
||||
|
||||
function sameLocation(a, b) {
|
||||
return a.start.line == b.start.line && a.start.column == b.start.column && a.end.line == b.end.line && a.end.column == b.end.column;
|
||||
}
|
||||
|
||||
function getFunctionParameterNames(path) {
|
||||
if (path.node.params != null) {
|
||||
return path.node.params.map(param => {
|
||||
if (param.type !== "AssignmentPattern") {
|
||||
return param.name;
|
||||
}
|
||||
|
||||
// Parameter with default value
|
||||
if (param.left.type === "Identifier" && param.right.type === "Identifier") {
|
||||
return `${param.left.name} = ${param.right.name}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "StringLiteral") {
|
||||
return `${param.left.name} = ${param.right.value}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ObjectExpression") {
|
||||
return `${param.left.name} = {}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ArrayExpression") {
|
||||
return `${param.left.name} = []`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "NullLiteral") {
|
||||
return `${param.left.name} = null`;
|
||||
}
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1455:
|
||||
@ -1313,28 +1348,15 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
||||
|
||||
let symbolDeclarations = new Map();
|
||||
|
||||
function getFunctionParameterNames(path) {
|
||||
if (path.node.params != null) {
|
||||
return path.node.params.map(param => {
|
||||
if (param.type !== "AssignmentPattern") {
|
||||
return param.name;
|
||||
}
|
||||
|
||||
// Parameter with default value
|
||||
if (param.left.type === "Identifier" && param.right.type === "Identifier") {
|
||||
return `${param.left.name} = ${param.right.name}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "StringLiteral") {
|
||||
return `${param.left.name} = ${param.right.value}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ObjectExpression") {
|
||||
return `${param.left.name} = {}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ArrayExpression") {
|
||||
return `${param.left.name} = []`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "NullLiteral") {
|
||||
return `${param.left.name} = null`;
|
||||
}
|
||||
});
|
||||
function getUniqueIdentifiers(identifiers) {
|
||||
const newIdentifiers = [];
|
||||
for (const newId of identifiers) {
|
||||
if (!newIdentifiers.find(id => (0, _helpers.nodeHasSameLocation)(id, newId))) {
|
||||
newIdentifiers.push(newId);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
|
||||
return newIdentifiers;
|
||||
}
|
||||
|
||||
/* eslint-disable complexity */
|
||||
@ -1345,7 +1367,7 @@ function extractSymbol(path, symbols) {
|
||||
name,
|
||||
klass: (0, _inferClassName.inferClassName)(path),
|
||||
location: path.node.loc,
|
||||
parameterNames: getFunctionParameterNames(path),
|
||||
parameterNames: (0, _helpers.getFunctionParameterNames)(path),
|
||||
identifier: path.node.id,
|
||||
// indicates the occurence of the function in a file
|
||||
// e.g { name: foo, ... index: 4 } is the 4th foo function
|
||||
@ -1442,7 +1464,7 @@ function extractSymbol(path, symbols) {
|
||||
});
|
||||
}
|
||||
|
||||
if (t.isIdentifier(path) && !t.isGenericTypeAnnotation(path.parent) && !t.isObjectProperty(path.parent) && !t.isArrayPattern(path.parent)) {
|
||||
if (t.isIdentifier(path) && !t.isGenericTypeAnnotation(path.parent)) {
|
||||
let { start, end } = path.node.loc;
|
||||
|
||||
// We want to include function params, but exclude the function name
|
||||
@ -1520,6 +1542,7 @@ function extractSymbols(sourceId) {
|
||||
|
||||
// comments are extracted separately from the AST
|
||||
symbols.comments = (0, _helpers.getComments)(ast);
|
||||
symbols.identifiers = getUniqueIdentifiers(symbols.identifiers);
|
||||
|
||||
return symbols;
|
||||
}
|
||||
@ -23060,6 +23083,13 @@ function mapOriginalExpression(expression, mappings) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ancestor = ancestors[ancestors.length - 1];
|
||||
// Shorthand properties can have a key and value with `node.loc.start` value
|
||||
// and we only want to replace the value.
|
||||
if (t.isObjectProperty(ancestor.node) && ancestor.key !== "value") {
|
||||
return;
|
||||
}
|
||||
|
||||
const replacement = replacements.get(locationKey(node.loc.start));
|
||||
if (replacement) {
|
||||
replaceNode(ancestors, t.cloneNode(replacement));
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
isPaused
|
||||
} from "../selectors";
|
||||
|
||||
import { mapFrames, fetchExtra } from "./pause";
|
||||
import { mapFrames } from "./pause";
|
||||
import { updateTab } from "./tabs";
|
||||
|
||||
import { PROMISE } from "./utils/middleware/promise";
|
||||
@ -67,7 +67,6 @@ export function setSymbols(sourceId: SourceId) {
|
||||
});
|
||||
|
||||
if (isPaused(getState())) {
|
||||
await dispatch(fetchExtra());
|
||||
await dispatch(mapFrames());
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
import { getSourceFromId } from "../../selectors";
|
||||
import * as parser from "../../workers/parser";
|
||||
import { isGenerated } from "../../utils/source";
|
||||
import { mapPausePoints } from "../../utils/pause/pausePoints";
|
||||
import { convertToList } from "../../utils/pause/pausePoints";
|
||||
import { features } from "../../utils/prefs";
|
||||
import { getGeneratedLocation } from "../../utils/source-maps";
|
||||
|
||||
@ -28,20 +28,24 @@ function compressPausePoints(pausePoints) {
|
||||
}
|
||||
|
||||
async function mapLocations(pausePoints, state, source, sourceMaps) {
|
||||
const pausePointList = convertToList(pausePoints);
|
||||
const sourceId = source.id;
|
||||
return mapPausePoints(pausePoints, async ({ types, location }) => {
|
||||
const generatedLocation = await getGeneratedLocation(
|
||||
state,
|
||||
source,
|
||||
{
|
||||
...location,
|
||||
sourceId
|
||||
},
|
||||
sourceMaps
|
||||
);
|
||||
|
||||
return { types, location, generatedLocation };
|
||||
});
|
||||
return Promise.all(
|
||||
pausePointList.map(async ({ types, location }) => {
|
||||
const generatedLocation = await getGeneratedLocation(
|
||||
state,
|
||||
source,
|
||||
{
|
||||
...location,
|
||||
sourceId
|
||||
},
|
||||
sourceMaps
|
||||
);
|
||||
|
||||
return { types, location, generatedLocation };
|
||||
})
|
||||
);
|
||||
}
|
||||
export function setPausePoints(sourceId: SourceId) {
|
||||
return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
|
||||
@ -56,6 +60,11 @@ export function setPausePoints(sourceId: SourceId) {
|
||||
|
||||
let pausePoints = await parser.getPausePoints(sourceId);
|
||||
|
||||
if (isGenerated(source)) {
|
||||
const compressed = compressPausePoints(pausePoints);
|
||||
await client.setPausePoints(sourceId, compressed);
|
||||
}
|
||||
|
||||
pausePoints = await mapLocations(
|
||||
pausePoints,
|
||||
getState(),
|
||||
@ -63,11 +72,6 @@ export function setPausePoints(sourceId: SourceId) {
|
||||
sourceMaps
|
||||
);
|
||||
|
||||
if (isGenerated(source)) {
|
||||
const compressed = compressPausePoints(pausePoints);
|
||||
await client.setPausePoints(sourceId, compressed);
|
||||
}
|
||||
|
||||
dispatch(
|
||||
({
|
||||
type: "SET_PAUSE_POINTS",
|
||||
|
@ -17,7 +17,8 @@ import {
|
||||
getXHRBreakpoints,
|
||||
getSelectedSource,
|
||||
getBreakpointAtLocation,
|
||||
getBreakpointsAtLine
|
||||
getBreakpointsAtLine,
|
||||
getBreakpointsForSource
|
||||
} from "../../selectors";
|
||||
import { assertBreakpoint, createXHRBreakpoint } from "../../utils/breakpoint";
|
||||
import {
|
||||
@ -32,7 +33,12 @@ import { isEmptyLineInSource } from "../../reducers/ast";
|
||||
// this will need to be changed so that addCLientBreakpoint is removed
|
||||
|
||||
import type { ThunkArgs, Action } from "../types";
|
||||
import type { Breakpoint, SourceLocation, XHRBreakpoint } from "../../types";
|
||||
import type {
|
||||
Breakpoint,
|
||||
Source,
|
||||
SourceLocation,
|
||||
XHRBreakpoint
|
||||
} from "../../types";
|
||||
|
||||
import { recordEvent } from "../../utils/telemetry";
|
||||
|
||||
@ -104,6 +110,40 @@ export function disableBreakpoint(location: SourceLocation) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all breakpoints in a source
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
export function disableBreakpointsInSource(source: Source) {
|
||||
return async ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
const breakpoints = getBreakpointsForSource(getState(), source.id);
|
||||
for (const breakpoint of breakpoints) {
|
||||
if (!breakpoint.disabled) {
|
||||
dispatch(disableBreakpoint(breakpoint.generatedLocation));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable all breakpoints in a source
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
export function enableBreakpointsInSource(source: Source) {
|
||||
return async ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
const breakpoints = getBreakpointsForSource(getState(), source.id);
|
||||
for (const breakpoint of breakpoints) {
|
||||
if (breakpoint.disabled) {
|
||||
dispatch(enableBreakpoint(breakpoint.generatedLocation));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle All Breakpoints
|
||||
*
|
||||
@ -196,6 +236,21 @@ export function removeBreakpoints(breakpoints: Breakpoint[]) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all breakpoints in a source
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
export function removeBreakpointsInSource(source: Source) {
|
||||
return async ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
const breakpoints = getBreakpointsForSource(getState(), source.id);
|
||||
for (const breakpoint of breakpoints) {
|
||||
dispatch(removeBreakpoint(breakpoint.generatedLocation));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function remapBreakpoints(sourceId: string) {
|
||||
return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => {
|
||||
const breakpoints = getBreakpointsList(getState());
|
||||
|
@ -5,6 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
getCurrentThread,
|
||||
getExpression,
|
||||
getExpressions,
|
||||
getSelectedFrame,
|
||||
@ -117,7 +118,11 @@ export function evaluateExpressions() {
|
||||
const expressions = getExpressions(getState()).toJS();
|
||||
const inputs = expressions.map(({ input }) => input);
|
||||
const frameId = getSelectedFrameId(getState());
|
||||
const results = await client.evaluateExpressions(inputs, frameId);
|
||||
const thread = getCurrentThread(getState());
|
||||
const results = await client.evaluateExpressions(inputs, {
|
||||
frameId,
|
||||
thread
|
||||
});
|
||||
dispatch({ type: "EVALUATE_EXPRESSIONS", inputs, results });
|
||||
};
|
||||
}
|
||||
@ -147,11 +152,16 @@ function evaluateExpression(expression: Expression) {
|
||||
}
|
||||
|
||||
const frameId = getSelectedFrameId(getState());
|
||||
const thread = getCurrentThread(getState());
|
||||
|
||||
return dispatch({
|
||||
type: "EVALUATE_EXPRESSION",
|
||||
thread,
|
||||
input: expression.input,
|
||||
[PROMISE]: client.evaluateInFrame(wrapExpression(input), frameId)
|
||||
[PROMISE]: client.evaluateInFrame(wrapExpression(input), {
|
||||
frameId,
|
||||
thread
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -54,10 +54,10 @@ export function navigate(url: string): Action {
|
||||
};
|
||||
}
|
||||
|
||||
export function connect(url: string, canRewind: boolean) {
|
||||
export function connect(url: string, thread: string, canRewind: boolean) {
|
||||
return async function({ dispatch }: ThunkArgs) {
|
||||
await dispatch(updateWorkers());
|
||||
dispatch(({ type: "CONNECT", url, canRewind }: Action));
|
||||
dispatch(({ type: "CONNECT", url, thread, canRewind }: Action));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import type { ThunkArgs } from "../types";
|
||||
import { getCurrentThread } from "../../selectors";
|
||||
|
||||
/**
|
||||
* Debugger breakOnNext command.
|
||||
@ -15,8 +16,9 @@ import type { ThunkArgs } from "../types";
|
||||
* @static
|
||||
*/
|
||||
export function breakOnNext() {
|
||||
return async ({ dispatch, client }: ThunkArgs) => {
|
||||
await client.breakOnNext();
|
||||
return dispatch({ type: "BREAK_ON_NEXT" });
|
||||
return async ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
const thread = getCurrentThread(getState());
|
||||
await client.breakOnNext(thread);
|
||||
return dispatch({ type: "BREAK_ON_NEXT", thread });
|
||||
};
|
||||
}
|
||||
|
@ -5,7 +5,12 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { isPaused, getSource, getTopFrame } from "../../selectors";
|
||||
import {
|
||||
isPaused,
|
||||
getCurrentThread,
|
||||
getSource,
|
||||
getTopFrame
|
||||
} from "../../selectors";
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { getNextStep } from "../../workers/parser";
|
||||
import { addHiddenBreakpoint } from "../breakpoints";
|
||||
@ -16,6 +21,15 @@ import type { Source } from "../../types";
|
||||
import type { ThunkArgs } from "../types";
|
||||
import type { Command } from "../../reducers/types";
|
||||
|
||||
export function selectThread(thread: string) {
|
||||
return async ({ dispatch, client }: ThunkArgs) => {
|
||||
return dispatch({
|
||||
type: "SELECT_THREAD",
|
||||
thread
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Debugger commands like stepOver, stepIn, stepUp
|
||||
*
|
||||
@ -24,11 +38,13 @@ import type { Command } from "../../reducers/types";
|
||||
* @static
|
||||
*/
|
||||
export function command(type: Command) {
|
||||
return async ({ dispatch, client }: ThunkArgs) => {
|
||||
return async ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
const thread = getCurrentThread(getState());
|
||||
return dispatch({
|
||||
type: "COMMAND",
|
||||
command: type,
|
||||
[PROMISE]: client[type]()
|
||||
thread,
|
||||
[PROMISE]: client[type](thread)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -4,7 +4,12 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { inComponent, getSelectedFrame } from "../../selectors";
|
||||
import {
|
||||
getCurrentThread,
|
||||
getSource,
|
||||
inComponent,
|
||||
getSelectedFrame
|
||||
} from "../../selectors";
|
||||
import { isImmutablePreview } from "../../utils/preview";
|
||||
|
||||
import type { ThunkArgs } from "../types";
|
||||
@ -77,6 +82,7 @@ export function fetchExtra() {
|
||||
const extra = await dispatch(getExtra("this;", frame.this));
|
||||
dispatch({
|
||||
type: "ADD_EXTRA",
|
||||
thread: getCurrentThread(getState()),
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
@ -89,8 +95,16 @@ export function getExtra(expression: string, result: Object) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const source = getSource(getState(), selectedFrame.location.sourceId);
|
||||
if (!source) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const extra = await getExtraProps(getState, expression, result, expr =>
|
||||
client.evaluateInFrame(expr, selectedFrame.id)
|
||||
client.evaluateInFrame(expr, {
|
||||
frameId: selectedFrame.id,
|
||||
thread: source.thread
|
||||
})
|
||||
);
|
||||
|
||||
return extra;
|
||||
|
@ -4,10 +4,13 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { getSelectedFrame, getGeneratedFrameScope } from "../../selectors";
|
||||
import {
|
||||
getCurrentThread,
|
||||
getSelectedFrame,
|
||||
getGeneratedFrameScope
|
||||
} from "../../selectors";
|
||||
import { mapScopes } from "./mapScopes";
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { fetchExtra } from "./extra";
|
||||
import type { ThunkArgs } from "../types";
|
||||
|
||||
export function fetchScopes() {
|
||||
@ -19,11 +22,11 @@ export function fetchScopes() {
|
||||
|
||||
const scopes = dispatch({
|
||||
type: "ADD_SCOPES",
|
||||
thread: getCurrentThread(getState()),
|
||||
frame,
|
||||
[PROMISE]: client.getFrameScopes(frame)
|
||||
});
|
||||
|
||||
await dispatch(fetchExtra());
|
||||
await dispatch(mapScopes(scopes, frame));
|
||||
};
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
export {
|
||||
selectThread,
|
||||
stepIn,
|
||||
stepOver,
|
||||
stepOut,
|
||||
@ -25,7 +26,6 @@ export { resumed } from "./resumed";
|
||||
export { continueToHere } from "./continueToHere";
|
||||
export { breakOnNext } from "./breakOnNext";
|
||||
export { mapFrames } from "./mapFrames";
|
||||
export { fetchExtra, getExtra } from "./extra";
|
||||
export { setPopupObjectProperties } from "./setPopupObjectProperties";
|
||||
export { pauseOnExceptions } from "./pauseOnExceptions";
|
||||
export { selectFrame } from "./selectFrame";
|
||||
|
@ -5,6 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
getCurrentThread,
|
||||
getFrames,
|
||||
getSymbols,
|
||||
getSource,
|
||||
@ -170,9 +171,11 @@ export function mapFrames() {
|
||||
mappedFrames = await expandFrames(mappedFrames, sourceMaps, getState);
|
||||
mappedFrames = mapDisplayNames(mappedFrames, getState);
|
||||
|
||||
const thread = getCurrentThread(getState());
|
||||
const selectedFrameId = getSelectedFrameId(getState(), mappedFrames);
|
||||
dispatch({
|
||||
type: "MAP_FRAMES",
|
||||
thread,
|
||||
frames: mappedFrames,
|
||||
selectedFrameId
|
||||
});
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { getSource } from "../../selectors";
|
||||
import { getCurrentThread, getSource } from "../../selectors";
|
||||
import { loadSourceText } from "../sources/loadSourceText";
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
|
||||
@ -28,6 +28,7 @@ export function mapScopes(scopes: Promise<Scope>, frame: Frame) {
|
||||
|
||||
await dispatch({
|
||||
type: "MAP_SCOPES",
|
||||
thread: getCurrentThread(getState()),
|
||||
frame,
|
||||
[PROMISE]: (async function() {
|
||||
if (
|
||||
|
@ -11,7 +11,6 @@ DebuggerModules(
|
||||
'breakOnNext.js',
|
||||
'commands.js',
|
||||
'continueToHere.js',
|
||||
'extra.js',
|
||||
'fetchScopes.js',
|
||||
'index.js',
|
||||
'mapFrames.js',
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { recordEvent } from "../../utils/telemetry";
|
||||
import type { ThunkArgs } from "../types";
|
||||
import { getCurrentThread } from "../../selectors";
|
||||
|
||||
/**
|
||||
*
|
||||
@ -17,7 +18,7 @@ export function pauseOnExceptions(
|
||||
shouldPauseOnExceptions: boolean,
|
||||
shouldPauseOnCaughtExceptions: boolean
|
||||
) {
|
||||
return ({ dispatch, client }: ThunkArgs) => {
|
||||
return ({ dispatch, getState, client }: ThunkArgs) => {
|
||||
/* eslint-disable camelcase */
|
||||
recordEvent("pause_on_exceptions", {
|
||||
exceptions: shouldPauseOnExceptions,
|
||||
@ -26,11 +27,14 @@ export function pauseOnExceptions(
|
||||
});
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
const thread = getCurrentThread(getState());
|
||||
return dispatch({
|
||||
type: "PAUSE_ON_EXCEPTIONS",
|
||||
thread,
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions,
|
||||
[PROMISE]: client.pauseOnExceptions(
|
||||
thread,
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ async function getOriginalSourceForFrame(state, frame: Frame) {
|
||||
*/
|
||||
export function paused(pauseInfo: Pause) {
|
||||
return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
|
||||
const { frames, why, loadedObjects } = pauseInfo;
|
||||
const { thread, frames, why, loadedObjects } = pauseInfo;
|
||||
const topFrame = frames.length > 0 ? frames[0] : null;
|
||||
|
||||
// NOTE: do not step when leaving a frame or paused at a debugger statement
|
||||
@ -57,6 +57,7 @@ export function paused(pauseInfo: Pause) {
|
||||
|
||||
dispatch({
|
||||
type: "PAUSED",
|
||||
thread,
|
||||
why,
|
||||
frames,
|
||||
selectedFrameId: topFrame ? topFrame.id : undefined,
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { isStepping, getPauseReason } from "../../selectors";
|
||||
import { getCurrentThread, isStepping, getPauseReason } from "../../selectors";
|
||||
import { evaluateExpressions } from "../expressions";
|
||||
import { inDebuggerEval } from "../../utils/pause";
|
||||
|
||||
@ -21,8 +21,9 @@ export function resumed() {
|
||||
const why = getPauseReason(getState());
|
||||
const wasPausedInEval = inDebuggerEval(why);
|
||||
const wasStepping = isStepping(getState());
|
||||
const thread = getCurrentThread(getState());
|
||||
|
||||
dispatch({ type: "RESUME" });
|
||||
dispatch({ type: "RESUME", thread });
|
||||
|
||||
if (!wasStepping && !wasPausedInEval) {
|
||||
await dispatch(evaluateExpressions());
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { selectLocation } from "../sources";
|
||||
import { evaluateExpressions } from "../expressions";
|
||||
import { fetchScopes } from "./fetchScopes";
|
||||
import { getCurrentThread } from "../../selectors";
|
||||
|
||||
import type { Frame } from "../../types";
|
||||
import type { ThunkArgs } from "../types";
|
||||
@ -19,6 +20,7 @@ export function selectFrame(frame: Frame) {
|
||||
return async ({ dispatch, client, getState, sourceMaps }: ThunkArgs) => {
|
||||
dispatch({
|
||||
type: "SELECT_FRAME",
|
||||
thread: getCurrentThread(getState()),
|
||||
frame
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { getPopupObjectProperties } from "../../selectors";
|
||||
import { getCurrentThread, getPopupObjectProperties } from "../../selectors";
|
||||
import type { ThunkArgs } from "../types";
|
||||
|
||||
/**
|
||||
@ -19,8 +19,10 @@ export function setPopupObjectProperties(object: any, properties: Object) {
|
||||
return;
|
||||
}
|
||||
|
||||
const thread = getCurrentThread(getState());
|
||||
dispatch({
|
||||
type: "SET_POPUP_OBJECT_PROPERTIES",
|
||||
thread,
|
||||
objectId,
|
||||
properties
|
||||
});
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import type { ThunkArgs } from "../types";
|
||||
import { getSkipPausing } from "../../selectors";
|
||||
import { getSkipPausing, getCurrentThread } from "../../selectors";
|
||||
|
||||
/**
|
||||
* @memberof actions/pause
|
||||
@ -13,8 +13,9 @@ import { getSkipPausing } from "../../selectors";
|
||||
*/
|
||||
export function toggleSkipPausing() {
|
||||
return async ({ dispatch, client, getState, sourceMaps }: ThunkArgs) => {
|
||||
const thread = getCurrentThread(getState());
|
||||
const skipPausing = !getSkipPausing(getState());
|
||||
await client.setSkipPausing(skipPausing);
|
||||
dispatch({ type: "TOGGLE_SKIP_PAUSING", skipPausing });
|
||||
await client.setSkipPausing(thread, skipPausing);
|
||||
dispatch({ type: "TOGGLE_SKIP_PAUSING", thread, skipPausing });
|
||||
};
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import {
|
||||
} from "../selectors";
|
||||
|
||||
import { getMappedExpression } from "./expressions";
|
||||
import { getExtra } from "./pause";
|
||||
|
||||
import type { Action, ThunkArgs } from "./types";
|
||||
import type { Position } from "../types";
|
||||
@ -100,24 +99,21 @@ export function setPreview(
|
||||
return;
|
||||
}
|
||||
|
||||
const { result } = await client.evaluateInFrame(
|
||||
expression,
|
||||
selectedFrame.id
|
||||
);
|
||||
const { result } = await client.evaluateInFrame(expression, {
|
||||
frameId: selectedFrame.id,
|
||||
thread: source.thread
|
||||
});
|
||||
|
||||
if (result === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extra = await dispatch(getExtra(expression, result));
|
||||
|
||||
return {
|
||||
expression,
|
||||
result,
|
||||
location,
|
||||
tokenPos,
|
||||
cursorPos,
|
||||
extra
|
||||
cursorPos
|
||||
};
|
||||
})()
|
||||
});
|
||||
|
@ -40,6 +40,7 @@ function createOriginalSource(
|
||||
url: originalUrl,
|
||||
relativeUrl: originalUrl,
|
||||
id: generatedToOriginalId(generatedSource.id, originalUrl),
|
||||
thread: "",
|
||||
isPrettyPrinted: false,
|
||||
isWasm: false,
|
||||
isBlackBoxed: false,
|
||||
|
@ -37,6 +37,7 @@ export function createPrettySource(sourceId: string) {
|
||||
url,
|
||||
relativeUrl: url,
|
||||
id,
|
||||
thread: "",
|
||||
isBlackBoxed: false,
|
||||
isPrettyPrinted: true,
|
||||
isWasm: false,
|
||||
|
@ -42,6 +42,7 @@ export const setSelectedLocation = (
|
||||
location: SourceLocation
|
||||
) => ({
|
||||
type: "SET_SELECTED_LOCATION",
|
||||
thread: source.thread,
|
||||
source,
|
||||
location
|
||||
});
|
||||
|
37
devtools/client/debugger/new/src/client/chrome.js
Normal file
37
devtools/client/debugger/new/src/client/chrome.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import { setupCommands, clientCommands } from "./chrome/commands";
|
||||
import { setupEvents, clientEvents, pageEvents } from "./chrome/events";
|
||||
|
||||
export async function onConnect(connection: any, actions: Object): Object {
|
||||
const {
|
||||
tabConnection,
|
||||
connTarget: { type }
|
||||
} = connection;
|
||||
const { Debugger, Runtime, Page } = tabConnection;
|
||||
|
||||
Debugger.enable();
|
||||
Debugger.setPauseOnExceptions({ state: "none" });
|
||||
Debugger.setAsyncCallStackDepth({ maxDepth: 0 });
|
||||
|
||||
if (type == "chrome") {
|
||||
Page.frameNavigated(pageEvents.frameNavigated);
|
||||
Page.frameStartedLoading(pageEvents.frameStartedLoading);
|
||||
Page.frameStoppedLoading(pageEvents.frameStoppedLoading);
|
||||
}
|
||||
|
||||
Debugger.scriptParsed(clientEvents.scriptParsed);
|
||||
Debugger.scriptFailedToParse(clientEvents.scriptFailedToParse);
|
||||
Debugger.paused(clientEvents.paused);
|
||||
Debugger.resumed(clientEvents.resumed);
|
||||
|
||||
setupCommands({ Debugger, Runtime, Page });
|
||||
setupEvents({ actions, Page, type, Runtime });
|
||||
return {};
|
||||
}
|
||||
|
||||
export { clientCommands, clientEvents };
|
144
devtools/client/debugger/new/src/client/chrome/commands.js
Normal file
144
devtools/client/debugger/new/src/client/chrome/commands.js
Normal file
@ -0,0 +1,144 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import {
|
||||
toServerLocation,
|
||||
fromServerLocation,
|
||||
createLoadedObject
|
||||
} from "./create";
|
||||
|
||||
import type { SourceLocation } from "../../types";
|
||||
import type { ServerLocation, Agents } from "./types";
|
||||
|
||||
type setBreakpointResponseType = {
|
||||
breakpointId: string,
|
||||
serverLocation?: ServerLocation
|
||||
};
|
||||
|
||||
let debuggerAgent;
|
||||
let runtimeAgent;
|
||||
let pageAgent;
|
||||
|
||||
function setupCommands({ Debugger, Runtime, Page }: Agents) {
|
||||
debuggerAgent = Debugger;
|
||||
runtimeAgent = Runtime;
|
||||
pageAgent = Page;
|
||||
}
|
||||
|
||||
function resume() {
|
||||
return debuggerAgent.resume();
|
||||
}
|
||||
|
||||
function stepIn() {
|
||||
return debuggerAgent.stepInto();
|
||||
}
|
||||
|
||||
function stepOver() {
|
||||
return debuggerAgent.stepOver();
|
||||
}
|
||||
|
||||
function stepOut() {
|
||||
return debuggerAgent.stepOut();
|
||||
}
|
||||
|
||||
function pauseOnExceptions(
|
||||
shouldPauseOnExceptions: boolean,
|
||||
shouldIgnoreCaughtExceptions: boolean
|
||||
) {
|
||||
if (!shouldPauseOnExceptions) {
|
||||
return debuggerAgent.setPauseOnExceptions({ state: "none" });
|
||||
}
|
||||
const state = shouldIgnoreCaughtExceptions ? "uncaught" : "all";
|
||||
return debuggerAgent.setPauseOnExceptions({ state });
|
||||
}
|
||||
|
||||
function breakOnNext() {
|
||||
return debuggerAgent.pause();
|
||||
}
|
||||
|
||||
function sourceContents(sourceId: string) {
|
||||
return debuggerAgent
|
||||
.getScriptSource({ scriptId: sourceId })
|
||||
.then(({ scriptSource }) => ({
|
||||
source: scriptSource,
|
||||
contentType: null
|
||||
}));
|
||||
}
|
||||
|
||||
async function setBreakpoint(location: SourceLocation, condition: string) {
|
||||
const {
|
||||
breakpointId,
|
||||
serverLocation
|
||||
}: setBreakpointResponseType = await debuggerAgent.setBreakpoint({
|
||||
location: toServerLocation(location),
|
||||
columnNumber: location.column
|
||||
});
|
||||
|
||||
const actualLocation = fromServerLocation(serverLocation) || location;
|
||||
|
||||
return {
|
||||
id: breakpointId,
|
||||
actualLocation: actualLocation
|
||||
};
|
||||
}
|
||||
|
||||
function removeBreakpoint(breakpointId: string) {
|
||||
return debuggerAgent.removeBreakpoint({ breakpointId });
|
||||
}
|
||||
|
||||
async function getProperties(object: any) {
|
||||
const { result } = await runtimeAgent.getProperties({
|
||||
objectId: object.objectId
|
||||
});
|
||||
|
||||
const loadedObjects = result.map(createLoadedObject);
|
||||
|
||||
return { loadedObjects };
|
||||
}
|
||||
|
||||
function evaluate(script: string) {
|
||||
return runtimeAgent.evaluate({ expression: script });
|
||||
}
|
||||
|
||||
function debuggeeCommand(script: string): Promise<void> {
|
||||
evaluate(script);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function navigate(url: string) {
|
||||
return pageAgent.navigate({ url });
|
||||
}
|
||||
|
||||
function getBreakpointByLocation(location: SourceLocation) {}
|
||||
|
||||
function setPausePoints() {}
|
||||
|
||||
function getFrameScopes() {}
|
||||
function evaluateInFrame() {}
|
||||
function evaluateExpressions() {}
|
||||
|
||||
const clientCommands = {
|
||||
resume,
|
||||
stepIn,
|
||||
stepOut,
|
||||
stepOver,
|
||||
pauseOnExceptions,
|
||||
breakOnNext,
|
||||
sourceContents,
|
||||
setBreakpoint,
|
||||
removeBreakpoint,
|
||||
evaluate,
|
||||
debuggeeCommand,
|
||||
navigate,
|
||||
getProperties,
|
||||
getBreakpointByLocation,
|
||||
setPausePoints,
|
||||
getFrameScopes,
|
||||
evaluateInFrame,
|
||||
evaluateExpressions
|
||||
};
|
||||
|
||||
export { setupCommands, clientCommands };
|
52
devtools/client/debugger/new/src/client/chrome/create.js
Normal file
52
devtools/client/debugger/new/src/client/chrome/create.js
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import type { SourceLocation, LoadedObject } from "../../types";
|
||||
import type { ServerLocation } from "./types";
|
||||
|
||||
export function fromServerLocation(
|
||||
serverLocation?: ServerLocation
|
||||
): ?SourceLocation {
|
||||
if (serverLocation) {
|
||||
return {
|
||||
sourceId: serverLocation.scriptId,
|
||||
line: serverLocation.lineNumber + 1,
|
||||
column: serverLocation.columnNumber,
|
||||
sourceUrl: ""
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function toServerLocation(location: SourceLocation): ServerLocation {
|
||||
return {
|
||||
scriptId: location.sourceId,
|
||||
lineNumber: location.line - 1
|
||||
};
|
||||
}
|
||||
|
||||
export function createFrame(frame: any) {
|
||||
return {
|
||||
id: frame.callFrameId,
|
||||
displayName: frame.functionName,
|
||||
scopeChain: frame.scopeChain,
|
||||
generatedLocation: frame.location,
|
||||
location: fromServerLocation(frame.location)
|
||||
};
|
||||
}
|
||||
|
||||
export function createLoadedObject(
|
||||
serverObject: any,
|
||||
parentId: string
|
||||
): LoadedObject {
|
||||
const { value, name } = serverObject;
|
||||
|
||||
return {
|
||||
objectId: value.objectId,
|
||||
parentId,
|
||||
name,
|
||||
value
|
||||
};
|
||||
}
|
122
devtools/client/debugger/new/src/client/chrome/events.js
Normal file
122
devtools/client/debugger/new/src/client/chrome/events.js
Normal file
@ -0,0 +1,122 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import { createFrame, createLoadedObject } from "./create";
|
||||
|
||||
let actions;
|
||||
let pageAgent;
|
||||
let clientType;
|
||||
let runtimeAgent;
|
||||
|
||||
function setupEvents(dependencies: any) {
|
||||
actions = dependencies.actions;
|
||||
pageAgent = dependencies.Page;
|
||||
clientType = dependencies.clientType;
|
||||
runtimeAgent = dependencies.Runtime;
|
||||
}
|
||||
|
||||
// Debugger Events
|
||||
function scriptParsed({
|
||||
scriptId,
|
||||
url,
|
||||
startLine,
|
||||
startColumn,
|
||||
endLine,
|
||||
endColumn,
|
||||
executionContextId,
|
||||
hash,
|
||||
isContentScript,
|
||||
isInternalScript,
|
||||
isLiveEdit,
|
||||
sourceMapURL,
|
||||
hasSourceURL,
|
||||
deprecatedCommentWasUsed
|
||||
}: any) {
|
||||
if (isContentScript) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientType == "node") {
|
||||
sourceMapURL = undefined;
|
||||
}
|
||||
|
||||
actions.newSource({
|
||||
id: scriptId,
|
||||
url,
|
||||
sourceMapURL,
|
||||
isPrettyPrinted: false
|
||||
});
|
||||
}
|
||||
|
||||
function scriptFailedToParse() {}
|
||||
|
||||
async function paused({
|
||||
callFrames,
|
||||
reason,
|
||||
data,
|
||||
hitBreakpoints,
|
||||
asyncStackTrace
|
||||
}: any) {
|
||||
const frames = callFrames.map(createFrame);
|
||||
const frame = frames[0];
|
||||
const why = { type: reason, ...data };
|
||||
|
||||
const objectId = frame.scopeChain[0].object.objectId;
|
||||
const { result } = await runtimeAgent.getProperties({
|
||||
objectId
|
||||
});
|
||||
|
||||
const loadedObjects = result.map(createLoadedObject);
|
||||
|
||||
if (clientType == "chrome") {
|
||||
pageAgent.configureOverlay({ message: "Paused in debugger.html" });
|
||||
}
|
||||
|
||||
await actions.paused({ frame, why, frames, loadedObjects });
|
||||
}
|
||||
|
||||
function resumed() {
|
||||
if (clientType == "chrome") {
|
||||
pageAgent.configureOverlay({ suspended: false });
|
||||
}
|
||||
|
||||
actions.resumed();
|
||||
}
|
||||
|
||||
function globalObjectCleared() {}
|
||||
|
||||
// Page Events
|
||||
function frameNavigated(frame: any) {
|
||||
actions.navigated();
|
||||
}
|
||||
|
||||
function frameStartedLoading() {
|
||||
actions.willNavigate();
|
||||
}
|
||||
|
||||
function domContentEventFired() {}
|
||||
|
||||
function loadEventFired() {}
|
||||
|
||||
function frameStoppedLoading() {}
|
||||
|
||||
const clientEvents = {
|
||||
scriptParsed,
|
||||
scriptFailedToParse,
|
||||
paused,
|
||||
resumed,
|
||||
globalObjectCleared
|
||||
};
|
||||
|
||||
const pageEvents = {
|
||||
frameNavigated,
|
||||
frameStartedLoading,
|
||||
domContentEventFired,
|
||||
loadEventFired,
|
||||
frameStoppedLoading
|
||||
};
|
||||
|
||||
export { setupEvents, pageEvents, clientEvents };
|
14
devtools/client/debugger/new/src/client/chrome/moz.build
Normal file
14
devtools/client/debugger/new/src/client/chrome/moz.build
Normal file
@ -0,0 +1,14 @@
|
||||
# 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 += [
|
||||
|
||||
]
|
||||
|
||||
DebuggerModules(
|
||||
'commands.js',
|
||||
'create.js',
|
||||
'events.js',
|
||||
)
|
@ -58,6 +58,7 @@ export async function onConnect(connection: any, actions: Object): Object {
|
||||
const traits = tabTarget.activeTab ? tabTarget.activeTab.traits : null;
|
||||
await actions.connect(
|
||||
tabTarget.url,
|
||||
threadClient.actor,
|
||||
traits && traits.canRewind
|
||||
);
|
||||
await actions.newSources(sources);
|
||||
@ -66,7 +67,7 @@ export async function onConnect(connection: any, actions: Object): Object {
|
||||
// paused state.
|
||||
const pausedPacket = threadClient.getLastPausePacket();
|
||||
if (pausedPacket) {
|
||||
clientEvents.paused("paused", pausedPacket);
|
||||
clientEvents.paused(threadClient, "paused", pausedPacket);
|
||||
}
|
||||
|
||||
return { bpClients };
|
||||
|
@ -25,15 +25,19 @@ import type {
|
||||
BPClients
|
||||
} from "./types";
|
||||
|
||||
import type { PausePoints } from "../../workers/parser";
|
||||
import type { PausePointsMap } from "../../workers/parser";
|
||||
|
||||
import { makePendingLocationId } from "../../utils/breakpoint";
|
||||
|
||||
import { createSource, createBreakpointLocation } from "./create";
|
||||
import { createSource, createBreakpointLocation, createWorker } from "./create";
|
||||
import { originalToGeneratedId, isOriginalId } from "devtools-source-map";
|
||||
import { supportsWorkers, updateWorkerClients } from "./workers";
|
||||
|
||||
import Services from "devtools-services";
|
||||
import { features } from "../../utils/prefs";
|
||||
|
||||
let bpClients: BPClients;
|
||||
let workerClients: Object;
|
||||
let sourceThreads: Object;
|
||||
let threadClient: ThreadClient;
|
||||
let tabTarget: TabTarget;
|
||||
let debuggerClient: DebuggerClient;
|
||||
@ -52,6 +56,8 @@ function setupCommands(dependencies: Dependencies): { bpClients: BPClients } {
|
||||
debuggerClient = dependencies.debuggerClient;
|
||||
supportsWasm = dependencies.supportsWasm;
|
||||
bpClients = {};
|
||||
workerClients = {};
|
||||
sourceThreads = {};
|
||||
|
||||
return { bpClients };
|
||||
}
|
||||
@ -72,60 +78,78 @@ function sendPacket(packet: Object, callback?: Function = r => r) {
|
||||
return debuggerClient.request(packet).then(callback);
|
||||
}
|
||||
|
||||
function resume(): Promise<*> {
|
||||
function lookupThreadClient(thread: string) {
|
||||
if (thread == threadClient.actor) {
|
||||
return threadClient;
|
||||
}
|
||||
if (!workerClients[thread]) {
|
||||
throw new Error(`Unknown thread client: ${thread}`);
|
||||
}
|
||||
return workerClients[thread].thread;
|
||||
}
|
||||
|
||||
function lookupConsoleClient(thread: string) {
|
||||
if (thread == threadClient.actor) {
|
||||
return tabTarget.activeConsole;
|
||||
}
|
||||
return workerClients[thread].console;
|
||||
}
|
||||
|
||||
function resume(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.resume(resolve);
|
||||
lookupThreadClient(thread).resume(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepIn(): Promise<*> {
|
||||
function stepIn(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepIn(resolve);
|
||||
lookupThreadClient(thread).stepIn(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepOver(): Promise<*> {
|
||||
function stepOver(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepOver(resolve);
|
||||
lookupThreadClient(thread).stepOver(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepOut(): Promise<*> {
|
||||
function stepOut(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepOut(resolve);
|
||||
lookupThreadClient(thread).stepOut(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function rewind(): Promise<*> {
|
||||
function rewind(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.rewind(resolve);
|
||||
lookupThreadClient(thread).rewind(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepIn(): Promise<*> {
|
||||
function reverseStepIn(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepIn(resolve);
|
||||
lookupThreadClient(thread).reverseStepIn(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepOver(): Promise<*> {
|
||||
function reverseStepOver(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepOver(resolve);
|
||||
lookupThreadClient(thread).reverseStepOver(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepOut(): Promise<*> {
|
||||
function reverseStepOut(thread: string): Promise<*> {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepOut(resolve);
|
||||
lookupThreadClient(thread).reverseStepOut(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function breakOnNext(): Promise<*> {
|
||||
return threadClient.breakOnNext();
|
||||
function breakOnNext(thread: string): Promise<*> {
|
||||
return lookupThreadClient(thread).breakOnNext();
|
||||
}
|
||||
|
||||
function sourceContents(sourceId: SourceId): Source {
|
||||
const sourceClient = threadClient.source({ actor: sourceId });
|
||||
const sourceThreadClient = sourceThreads[sourceId];
|
||||
const sourceClient = sourceThreadClient.source({ actor: sourceId });
|
||||
return sourceClient.source();
|
||||
}
|
||||
|
||||
@ -162,7 +186,8 @@ function setBreakpoint(
|
||||
condition: boolean,
|
||||
noSliding: boolean
|
||||
): Promise<BreakpointResult> {
|
||||
const sourceClient = threadClient.source({ actor: location.sourceId });
|
||||
const sourceThreadClient = sourceThreads[location.sourceId];
|
||||
const sourceClient = sourceThreadClient.source({ actor: location.sourceId });
|
||||
|
||||
return sourceClient
|
||||
.setBreakpoint({
|
||||
@ -209,39 +234,43 @@ function setBreakpointCondition(
|
||||
const bpClient = bpClients[breakpointId];
|
||||
delete bpClients[breakpointId];
|
||||
|
||||
const sourceThreadClient = sourceThreads[bpClient.source.actor];
|
||||
return bpClient
|
||||
.setCondition(threadClient, condition, noSliding)
|
||||
.setCondition(sourceThreadClient, condition, noSliding)
|
||||
.then(_bpClient => {
|
||||
bpClients[breakpointId] = _bpClient;
|
||||
return { id: breakpointId };
|
||||
});
|
||||
}
|
||||
|
||||
async function evaluateInFrame(script: Script, frameId: string) {
|
||||
return evaluate(script, { frameId });
|
||||
async function evaluateInFrame(script: Script, options: EvaluateParam) {
|
||||
return evaluate(script, options);
|
||||
}
|
||||
|
||||
async function evaluateExpressions(scripts: Script[], frameId?: string) {
|
||||
return Promise.all(scripts.map(script => evaluate(script, { frameId })));
|
||||
async function evaluateExpressions(scripts: Script[], options: EvaluateParam) {
|
||||
return Promise.all(scripts.map(script => evaluate(script, options)));
|
||||
}
|
||||
|
||||
type EvaluateParam = { frameId?: FrameId };
|
||||
type EvaluateParam = { thread?: string, frameId?: FrameId };
|
||||
|
||||
function evaluate(
|
||||
script: ?Script,
|
||||
{ frameId }: EvaluateParam = {}
|
||||
{ thread, frameId }: EvaluateParam = {}
|
||||
): Promise<mixed> {
|
||||
const params = frameId ? { frameActor: frameId } : {};
|
||||
if (!tabTarget || !tabTarget.activeConsole || !script) {
|
||||
const params = { thread, frameActor: frameId };
|
||||
if (!tabTarget || !script) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
const console = thread
|
||||
? lookupConsoleClient(thread)
|
||||
: tabTarget.activeConsole;
|
||||
if (!console) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
tabTarget.activeConsole.evaluateJSAsync(
|
||||
script,
|
||||
result => resolve(result),
|
||||
params
|
||||
);
|
||||
console.evaluateJSAsync(script, result => resolve(result), params);
|
||||
});
|
||||
}
|
||||
|
||||
@ -271,8 +300,8 @@ function reload(): Promise<*> {
|
||||
return tabTarget.activeTab.reload();
|
||||
}
|
||||
|
||||
function getProperties(grip: Grip): Promise<*> {
|
||||
const objClient = threadClient.pauseGrip(grip);
|
||||
function getProperties(thread: string, grip: Grip): Promise<*> {
|
||||
const objClient = lookupThreadClient(thread).pauseGrip(grip);
|
||||
|
||||
return objClient.getPrototypeAndProperties().then(resp => {
|
||||
const { ownProperties, safeGetterValues } = resp;
|
||||
@ -289,14 +318,21 @@ async function getFrameScopes(frame: Frame): Promise<*> {
|
||||
return frame.scope;
|
||||
}
|
||||
|
||||
return threadClient.getEnvironment(frame.id);
|
||||
let sourceId = frame.location.sourceId;
|
||||
if (isOriginalId(sourceId)) {
|
||||
sourceId = originalToGeneratedId(sourceId);
|
||||
}
|
||||
|
||||
const sourceThreadClient = sourceThreads[sourceId];
|
||||
return sourceThreadClient.getEnvironment(frame.id);
|
||||
}
|
||||
|
||||
function pauseOnExceptions(
|
||||
thread: string,
|
||||
shouldPauseOnExceptions: boolean,
|
||||
shouldPauseOnCaughtExceptions: boolean
|
||||
): Promise<*> {
|
||||
return threadClient.pauseOnExceptions(
|
||||
return lookupThreadClient(thread).pauseOnExceptions(
|
||||
shouldPauseOnExceptions,
|
||||
// Providing opposite value because server
|
||||
// uses "shouldIgnoreCaughtExceptions"
|
||||
@ -325,91 +361,97 @@ function disablePrettyPrint(sourceId: SourceId): Promise<*> {
|
||||
return sourceClient.disablePrettyPrint();
|
||||
}
|
||||
|
||||
async function setPausePoints(sourceId: SourceId, pausePoints: PausePoints) {
|
||||
async function setPausePoints(sourceId: SourceId, pausePoints: PausePointsMap) {
|
||||
return sendPacket({ to: sourceId, type: "setPausePoints", pausePoints });
|
||||
}
|
||||
|
||||
async function setSkipPausing(shouldSkip: boolean) {
|
||||
return threadClient.request({
|
||||
async function setSkipPausing(thread: string, shouldSkip: boolean) {
|
||||
const client = lookupThreadClient(thread);
|
||||
return client.request({
|
||||
skip: shouldSkip,
|
||||
to: threadClient.actor,
|
||||
to: client.actor,
|
||||
type: "skipBreakpoints"
|
||||
});
|
||||
}
|
||||
|
||||
function interrupt(): Promise<*> {
|
||||
return threadClient.interrupt();
|
||||
function interrupt(thread: string): Promise<*> {
|
||||
return lookupThreadClient(thread).interrupt();
|
||||
}
|
||||
|
||||
function eventListeners(): Promise<*> {
|
||||
return threadClient.eventListeners();
|
||||
}
|
||||
|
||||
function pauseGrip(func: Function): ObjectClient {
|
||||
return threadClient.pauseGrip(func);
|
||||
function pauseGrip(thread: string, func: Function): ObjectClient {
|
||||
return lookupThreadClient(thread).pauseGrip(func);
|
||||
}
|
||||
|
||||
async function fetchSources() {
|
||||
const { sources } = await threadClient.getSources();
|
||||
function registerSource(source: Source) {
|
||||
if (isOriginalId(source.id)) {
|
||||
throw new Error("registerSource called with original ID");
|
||||
}
|
||||
sourceThreads[source.id] = lookupThreadClient(source.thread);
|
||||
}
|
||||
|
||||
async function createSources(client: ThreadClient) {
|
||||
const { sources } = await client.getSources();
|
||||
return (
|
||||
sources &&
|
||||
sources.map(packet => createSource(client.actor, packet, { supportsWasm }))
|
||||
);
|
||||
}
|
||||
|
||||
async function fetchSources(): Promise<any[]> {
|
||||
let sources = await createSources(threadClient);
|
||||
|
||||
// NOTE: this happens when we fetch sources and then immediately navigate
|
||||
if (!sources) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
return sources.map(source => createSource(source, { supportsWasm }));
|
||||
}
|
||||
if (features.windowlessWorkers) {
|
||||
// Also fetch sources from any workers.
|
||||
workerClients = await updateWorkerClients({
|
||||
threadClient,
|
||||
debuggerClient,
|
||||
tabTarget,
|
||||
workerClients
|
||||
});
|
||||
|
||||
/**
|
||||
* Temporary helper to check if the current server will support a call to
|
||||
* listWorkers. On Fennec 60 or older, the call will silently crash and prevent
|
||||
* the client from resuming.
|
||||
* XXX: Remove when FF60 for Android is no longer used or available.
|
||||
*
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1443550 for more details.
|
||||
*/
|
||||
async function checkServerSupportsListWorkers() {
|
||||
const root = await tabTarget.root;
|
||||
// root is not available on all debug targets.
|
||||
if (!root) {
|
||||
return false;
|
||||
const workerNames = Object.getOwnPropertyNames(workerClients);
|
||||
workerNames.forEach(actor => {
|
||||
const workerSources = createSources(workerClients[actor].thread);
|
||||
if (workerSources) {
|
||||
sources = sources.concat(workerSources);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const deviceFront = await debuggerClient.mainRoot.getFront("device");
|
||||
const description = await deviceFront.getDescription();
|
||||
|
||||
const isFennec = description.apptype === "mobile/android";
|
||||
if (!isFennec) {
|
||||
// Explicitly return true early to avoid calling Services.vs.compare.
|
||||
// This would force us to extent the Services shim provided by
|
||||
// devtools-modules, used when this code runs in a tab.
|
||||
return true;
|
||||
}
|
||||
|
||||
// We are only interested in Fennec release versions here.
|
||||
// We assume that the server fix for Bug 1443550 will land in FF61.
|
||||
const version = description.platformversion;
|
||||
return Services.vc.compare(version, "61.0") >= 0;
|
||||
return sources;
|
||||
}
|
||||
|
||||
async function fetchWorkers(): Promise<{ workers: Worker[] }> {
|
||||
// Temporary workaround for Bug 1443550
|
||||
// XXX: Remove when FF60 for Android is no longer used or available.
|
||||
const supportsListWorkers = await checkServerSupportsListWorkers();
|
||||
if (features.windowlessWorkers) {
|
||||
workerClients = await updateWorkerClients({
|
||||
tabTarget,
|
||||
debuggerClient,
|
||||
threadClient,
|
||||
workerClients
|
||||
});
|
||||
|
||||
// NOTE: The Worker and Browser Content toolboxes do not have a parent
|
||||
// with a listWorkers function
|
||||
// TODO: there is a listWorkers property, but it is not a function on the
|
||||
// parent. Investigate what it is
|
||||
if (
|
||||
!threadClient._parent ||
|
||||
typeof threadClient._parent.listWorkers != "function" ||
|
||||
!supportsListWorkers
|
||||
) {
|
||||
const workerNames = Object.getOwnPropertyNames(workerClients);
|
||||
return {
|
||||
workers: workerNames.map(actor =>
|
||||
createWorker(actor, workerClients[actor].url)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
if (!supportsWorkers(tabTarget)) {
|
||||
return Promise.resolve({ workers: [] });
|
||||
}
|
||||
|
||||
return threadClient._parent.listWorkers();
|
||||
return tabTarget.activeTab.listWorkers();
|
||||
}
|
||||
|
||||
const clientCommands = {
|
||||
@ -450,7 +492,8 @@ const clientCommands = {
|
||||
fetchWorkers,
|
||||
sendPacket,
|
||||
setPausePoints,
|
||||
setSkipPausing
|
||||
setSkipPausing,
|
||||
registerSource
|
||||
};
|
||||
|
||||
export { setupCommands, clientCommands };
|
||||
|
@ -13,6 +13,8 @@ import type {
|
||||
SourcePayload
|
||||
} from "./types";
|
||||
|
||||
import { clientCommands } from "./commands";
|
||||
|
||||
export function createFrame(frame: FramePacket): ?Frame {
|
||||
if (!frame) {
|
||||
return null;
|
||||
@ -41,11 +43,13 @@ export function createFrame(frame: FramePacket): ?Frame {
|
||||
}
|
||||
|
||||
export function createSource(
|
||||
thread: string,
|
||||
source: SourcePayload,
|
||||
{ supportsWasm }: { supportsWasm: boolean }
|
||||
): Source {
|
||||
const createdSource = {
|
||||
id: source.actor,
|
||||
thread,
|
||||
url: source.url,
|
||||
relativeUrl: source.url,
|
||||
isPrettyPrinted: false,
|
||||
@ -54,12 +58,14 @@ export function createSource(
|
||||
isBlackBoxed: false,
|
||||
loadedState: "unloaded"
|
||||
};
|
||||
clientCommands.registerSource(createdSource);
|
||||
return Object.assign(createdSource, {
|
||||
isWasm: supportsWasm && source.introductionType === "wasm"
|
||||
});
|
||||
}
|
||||
|
||||
export function createPause(
|
||||
thread: string,
|
||||
packet: PausedPacket,
|
||||
response: FramesResponse
|
||||
): any {
|
||||
@ -68,6 +74,7 @@ export function createPause(
|
||||
|
||||
return {
|
||||
...packet,
|
||||
thread,
|
||||
frame: createFrame(frame),
|
||||
frames: response.frames.map(createFrame)
|
||||
};
|
||||
@ -92,3 +99,12 @@ export function createBreakpointLocation(
|
||||
column: actualLocation.column
|
||||
};
|
||||
}
|
||||
|
||||
export function createWorker(actor: string, url: string) {
|
||||
return {
|
||||
actor,
|
||||
url,
|
||||
// Ci.nsIWorkerDebugger.TYPE_DEDICATED
|
||||
type: 0
|
||||
};
|
||||
}
|
||||
|
@ -23,21 +23,24 @@ type Dependencies = {
|
||||
supportsWasm: boolean
|
||||
};
|
||||
|
||||
let threadClient: ThreadClient;
|
||||
let actions: Actions;
|
||||
let supportsWasm: boolean;
|
||||
let isInterrupted: boolean;
|
||||
|
||||
function addThreadEventListeners(client: ThreadClient) {
|
||||
Object.keys(clientEvents).forEach(eventName => {
|
||||
client.addListener(eventName, clientEvents[eventName].bind(null, client));
|
||||
});
|
||||
}
|
||||
|
||||
function setupEvents(dependencies: Dependencies) {
|
||||
threadClient = dependencies.threadClient;
|
||||
const threadClient = dependencies.threadClient;
|
||||
actions = dependencies.actions;
|
||||
supportsWasm = dependencies.supportsWasm;
|
||||
sourceQueue.initialize(actions);
|
||||
|
||||
if (threadClient) {
|
||||
Object.keys(clientEvents).forEach(eventName => {
|
||||
threadClient.addListener(eventName, clientEvents[eventName]);
|
||||
});
|
||||
addThreadEventListeners(threadClient);
|
||||
|
||||
if (threadClient._parent) {
|
||||
// Parent may be BrowsingContextTargetFront/WorkerTargetFront and
|
||||
@ -54,7 +57,11 @@ function setupEvents(dependencies: Dependencies) {
|
||||
}
|
||||
}
|
||||
|
||||
async function paused(_: "paused", packet: PausedPacket) {
|
||||
async function paused(
|
||||
threadClient: ThreadClient,
|
||||
_: "paused",
|
||||
packet: PausedPacket
|
||||
) {
|
||||
// If paused by an explicit interrupt, which are generated by the
|
||||
// slow script dialog and internal events such as setting
|
||||
// breakpoints, ignore the event.
|
||||
@ -79,13 +86,17 @@ async function paused(_: "paused", packet: PausedPacket) {
|
||||
}
|
||||
|
||||
if (why.type != "alreadyPaused") {
|
||||
const pause = createPause(packet, response);
|
||||
const pause = createPause(threadClient.actor, packet, response);
|
||||
await sourceQueue.flush();
|
||||
actions.paused(pause);
|
||||
}
|
||||
}
|
||||
|
||||
function resumed(_: "resumed", packet: ResumedPacket) {
|
||||
function resumed(
|
||||
threadClient: ThreadClient,
|
||||
_: "resumed",
|
||||
packet: ResumedPacket
|
||||
) {
|
||||
// NOTE: the client suppresses resumed events while interrupted
|
||||
// to prevent unintentional behavior.
|
||||
// see [client docs](../README.md#interrupted) for more information.
|
||||
@ -97,8 +108,12 @@ function resumed(_: "resumed", packet: ResumedPacket) {
|
||||
actions.resumed(packet);
|
||||
}
|
||||
|
||||
function newSource(_: "newSource", { source }: SourcePacket) {
|
||||
sourceQueue.queue(createSource(source, { supportsWasm }));
|
||||
function newSource(
|
||||
threadClient: ThreadClient,
|
||||
_: "newSource",
|
||||
{ source }: SourcePacket
|
||||
) {
|
||||
sourceQueue.queue(createSource(threadClient.actor, source, { supportsWasm }));
|
||||
}
|
||||
|
||||
function workerListChanged() {
|
||||
@ -111,4 +126,4 @@ const clientEvents = {
|
||||
newSource
|
||||
};
|
||||
|
||||
export { setupEvents, clientEvents };
|
||||
export { setupEvents, clientEvents, addThreadEventListeners };
|
||||
|
@ -11,4 +11,5 @@ DebuggerModules(
|
||||
'commands.js',
|
||||
'create.js',
|
||||
'events.js',
|
||||
'workers.js',
|
||||
)
|
||||
|
54
devtools/client/debugger/new/src/client/firefox/workers.js
Normal file
54
devtools/client/debugger/new/src/client/firefox/workers.js
Normal file
@ -0,0 +1,54 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import { addThreadEventListeners } from "./events";
|
||||
import type { TabTarget } from "./types";
|
||||
|
||||
export function supportsWorkers(tabTarget: TabTarget) {
|
||||
return tabTarget.isBrowsingContext || tabTarget.isContentProcess;
|
||||
}
|
||||
|
||||
export async function updateWorkerClients({
|
||||
tabTarget,
|
||||
debuggerClient,
|
||||
threadClient,
|
||||
workerClients
|
||||
}: Object) {
|
||||
if (!supportsWorkers(tabTarget)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const newWorkerClients = {};
|
||||
|
||||
const { workers } = await tabTarget.activeTab.listWorkers();
|
||||
for (const workerTargetFront of workers) {
|
||||
await workerTargetFront.attach();
|
||||
const [, workerThread] = await workerTargetFront.attachThread();
|
||||
|
||||
if (workerClients[workerThread.actor]) {
|
||||
if (workerClients[workerThread.actor].thread != workerThread) {
|
||||
throw new Error(`Multiple clients for actor ID: ${workerThread.actor}`);
|
||||
}
|
||||
newWorkerClients[workerThread.actor] = workerClients[workerThread.actor];
|
||||
} else {
|
||||
addThreadEventListeners(workerThread);
|
||||
workerThread.resume();
|
||||
|
||||
const [, consoleClient] = await debuggerClient.attachConsole(
|
||||
workerTargetFront.targetForm.consoleActor,
|
||||
[]
|
||||
);
|
||||
|
||||
newWorkerClients[workerThread.actor] = {
|
||||
url: workerTargetFront.url,
|
||||
thread: workerThread,
|
||||
console: consoleClient
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return newWorkerClients;
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import * as firefox from "./firefox";
|
||||
import * as chrome from "./chrome";
|
||||
|
||||
import { prefs, asyncStore } from "../utils/prefs";
|
||||
import { setupHelper } from "../utils/dbg";
|
||||
@ -46,6 +47,13 @@ async function loadInitialState() {
|
||||
return { pendingBreakpoints, tabs, breakpoints };
|
||||
}
|
||||
|
||||
function getClient(connection: any) {
|
||||
const {
|
||||
tab: { clientType }
|
||||
} = connection;
|
||||
return clientType == "firefox" ? firefox : chrome;
|
||||
}
|
||||
|
||||
export async function onConnect(
|
||||
connection: Object,
|
||||
{ services, toolboxActions }: Object
|
||||
@ -55,8 +63,11 @@ export async function onConnect(
|
||||
return;
|
||||
}
|
||||
|
||||
const commands = firefox.clientCommands;
|
||||
const client = getClient(connection);
|
||||
const commands = client.clientCommands;
|
||||
|
||||
const initialState = await loadInitialState();
|
||||
|
||||
const { store, actions, selectors } = bootstrapStore(
|
||||
commands,
|
||||
{
|
||||
@ -67,7 +78,8 @@ export async function onConnect(
|
||||
);
|
||||
|
||||
const workers = bootstrapWorkers();
|
||||
await firefox.onConnect(connection, actions);
|
||||
await client.onConnect(connection, actions);
|
||||
|
||||
await loadFromPrefs(actions);
|
||||
syncXHRBreakpoints();
|
||||
setupHelper({
|
||||
@ -76,7 +88,7 @@ export async function onConnect(
|
||||
selectors,
|
||||
workers: { ...workers, ...services },
|
||||
connection,
|
||||
client: firefox.clientCommands
|
||||
client: client.clientCommands
|
||||
});
|
||||
|
||||
bootstrapApp(store);
|
||||
|
@ -4,10 +4,12 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'chrome',
|
||||
'firefox',
|
||||
]
|
||||
|
||||
DebuggerModules(
|
||||
'chrome.js',
|
||||
'firefox.js',
|
||||
'index.js',
|
||||
)
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
// @flow
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import classnames from "classnames";
|
||||
|
||||
import { connect } from "../utils/connect";
|
||||
import { prefs, features } from "../utils/prefs";
|
||||
import actions from "../actions";
|
||||
import A11yIntention from "./A11yIntention";
|
||||
@ -44,6 +44,8 @@ import "./App.css";
|
||||
// $FlowIgnore
|
||||
import "devtools-launchpad/src/components/Root.css";
|
||||
|
||||
import type { ActiveSearchType } from "../selectors";
|
||||
|
||||
import "./shared/menu.css";
|
||||
import "./shared/reps.css";
|
||||
|
||||
@ -61,7 +63,7 @@ type Props = {
|
||||
orientation: OrientationType,
|
||||
startPanelCollapsed: boolean,
|
||||
endPanelCollapsed: boolean,
|
||||
activeSearch: string,
|
||||
activeSearch: ActiveSearchType,
|
||||
quickOpenEnabled: boolean,
|
||||
canRewind: boolean,
|
||||
setActiveSearch: typeof actions.setActiveSearch,
|
||||
|
@ -3,13 +3,13 @@
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
// @flow
|
||||
import { connect } from "react-redux";
|
||||
import React, { Component } from "react";
|
||||
import Breakpoint from "./Breakpoint";
|
||||
|
||||
import { getSelectedSource, getFirstVisibleBreakpoints } from "../../selectors";
|
||||
import { makeLocationId } from "../../utils/breakpoint";
|
||||
import { isLoaded } from "../../utils/source";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
import type { Breakpoint as BreakpointType, Source } from "../../types";
|
||||
|
||||
|
@ -3,12 +3,12 @@
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import ColumnBreakpoint from "./ColumnBreakpoint";
|
||||
import "./ColumnBreakpoints.css";
|
||||
|
||||
import { getSelectedSource, visibleColumnBreakpoints } from "../../selectors";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { makeLocationId } from "../../utils/breakpoint";
|
||||
import actions from "../../actions";
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
import React, { PureComponent } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import "./ConditionalPanel.css";
|
||||
import { toEditorLine } from "../../utils/editor";
|
||||
import actions from "../../actions";
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
import { isLoaded } from "../../utils/source";
|
||||
import { isException } from "../../utils/pause";
|
||||
import { getIndentation } from "../../utils/indentation";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import {
|
||||
getVisibleSelectedFrame,
|
||||
getPauseReason,
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { showMenu } from "devtools-contextmenu";
|
||||
import { isOriginalId } from "devtools-source-map";
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* 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/>. */
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { Component } from "react";
|
||||
import { getSelectedSource, getEmptyLines } from "../../selectors";
|
||||
import type { Source } from "../../types";
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import Svg from "../shared/Svg";
|
||||
import actions from "../../actions";
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import { Component } from "react";
|
||||
import { showMenu } from "devtools-contextmenu";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { lineAtHeight } from "../../utils/editor";
|
||||
import {
|
||||
getContextMenu,
|
||||
|
@ -8,7 +8,7 @@ import { toEditorLine, endOperation, startOperation } from "../../utils/editor";
|
||||
import { getDocument, hasDocument } from "../../utils/editor/source-documents";
|
||||
import { isLoaded } from "../../utils/source";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import {
|
||||
getVisibleSelectedFrame,
|
||||
getSelectedLocation,
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
import { Component } from "react";
|
||||
import { range, isEmpty } from "lodash";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { getHighlightedLineRange } from "../../selectors";
|
||||
|
||||
type Props = {
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
|
||||
import Reps from "devtools-reps";
|
||||
const {
|
||||
@ -17,7 +17,7 @@ const {
|
||||
const { ObjectInspector, utils } = objectInspector;
|
||||
|
||||
const {
|
||||
node: { createNode, getChildren, getValue, nodeIsPrimitive, NODE_TYPES },
|
||||
node: { createNode, getChildren, getValue, nodeIsPrimitive },
|
||||
loadProperties: { loadItemProperties }
|
||||
} = utils;
|
||||
|
||||
@ -25,7 +25,6 @@ import actions from "../../../actions";
|
||||
import { getAllPopupObjectProperties } from "../../../selectors";
|
||||
import Popover from "../../shared/Popover";
|
||||
import PreviewFunction from "../../shared/PreviewFunction";
|
||||
import { isReactComponent, isImmutablePreview } from "../../../utils/preview";
|
||||
|
||||
import Svg from "../../shared/Svg";
|
||||
import { createObjectClient } from "../../../client/firefox";
|
||||
@ -45,7 +44,6 @@ type Props = {
|
||||
range: EditorRange,
|
||||
editor: any,
|
||||
editorRef: ?HTMLDivElement,
|
||||
extra: Object,
|
||||
setPopupObjectProperties: typeof actions.setPopupObjectProperties,
|
||||
addExpression: typeof actions.addExpression,
|
||||
selectSourceURL: typeof actions.selectSourceURL,
|
||||
@ -129,17 +127,12 @@ export class Popup extends Component<Props, State> {
|
||||
};
|
||||
|
||||
getRoot() {
|
||||
const { expression, value, extra } = this.props;
|
||||
|
||||
let rootValue = value;
|
||||
if (extra.immutable) {
|
||||
rootValue = extra.immutable.entries;
|
||||
}
|
||||
const { expression, value } = this.props;
|
||||
|
||||
return createNode({
|
||||
name: expression,
|
||||
path: expression,
|
||||
contents: { value: rootValue }
|
||||
contents: { value }
|
||||
});
|
||||
}
|
||||
|
||||
@ -223,33 +216,22 @@ export class Popup extends Component<Props, State> {
|
||||
}
|
||||
|
||||
renderObjectPreview() {
|
||||
const { extra, value } = this.props;
|
||||
const root = this.getRoot();
|
||||
|
||||
if (nodeIsPrimitive(root)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let roots = this.getChildren();
|
||||
const roots = this.getChildren();
|
||||
if (!Array.isArray(roots) || roots.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let header = null;
|
||||
if (extra.immutable && isImmutablePreview(value)) {
|
||||
header = this.renderImmutable(extra.immutable);
|
||||
roots = roots.filter(r => r.type != NODE_TYPES.PROTOTYPE);
|
||||
} else if (extra.react && isReactComponent(this.getObjectProperties())) {
|
||||
header = this.renderReact(extra.react);
|
||||
roots = roots.filter(r => ["state", "props"].includes(r.name));
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="preview-popup"
|
||||
style={{ maxHeight: this.calculateMaxHeight() }}
|
||||
>
|
||||
{header}
|
||||
{this.renderObjectInspector(roots)}
|
||||
</div>
|
||||
);
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
|
||||
import Popup from "./Popup";
|
||||
|
||||
@ -22,7 +22,7 @@ type Props = {
|
||||
editorRef: ?HTMLDivElement,
|
||||
selectedSource: Source,
|
||||
preview: PreviewType,
|
||||
isPaused: Boolean,
|
||||
isPaused: boolean,
|
||||
clearPreview: typeof actions.clearPreview,
|
||||
setPopupObjectProperties: typeof actions.setPopupObjectProperties,
|
||||
addExpression: typeof actions.addExpression,
|
||||
@ -148,7 +148,7 @@ class Preview extends PureComponent<Props, State> {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { result, expression, location, cursorPos, extra } = preview;
|
||||
const { result, expression, location, cursorPos } = preview;
|
||||
const value = result;
|
||||
if (typeof value == "undefined" || value.optimizedOut) {
|
||||
return null;
|
||||
@ -164,7 +164,6 @@ class Preview extends PureComponent<Props, State> {
|
||||
range={editorRange}
|
||||
expression={expression}
|
||||
popoverPos={cursorPos}
|
||||
extra={extra}
|
||||
onClose={this.onClose}
|
||||
/>
|
||||
);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { CloseButton } from "../shared/Button";
|
||||
import Svg from "../shared/Svg";
|
||||
import actions from "../../actions";
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
import { showMenu, buildMenu } from "devtools-contextmenu";
|
||||
|
||||
@ -35,6 +35,7 @@ import {
|
||||
getSourcesForTabs,
|
||||
getHasSiblingOfSameName
|
||||
} from "../../selectors";
|
||||
import type { ActiveSearchType } from "../../selectors";
|
||||
|
||||
import classnames from "classnames";
|
||||
|
||||
@ -44,7 +45,7 @@ type Props = {
|
||||
tabSources: SourcesList,
|
||||
selectedSource: Source,
|
||||
source: Source,
|
||||
activeSearch: string,
|
||||
activeSearch: ActiveSearchType,
|
||||
hasSiblingOfSameName: boolean,
|
||||
selectSource: typeof actions.selectSource,
|
||||
closeTab: typeof actions.closeTab,
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
import { getSelectedSource, getSourcesForTabs } from "../../selectors";
|
||||
import { isVisible } from "../../utils/ui";
|
||||
|
@ -7,7 +7,7 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React, { PureComponent } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import { debounce } from "lodash";
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { showMenu } from "devtools-contextmenu";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { score as fuzzaldrinScore } from "fuzzaldrin-plus";
|
||||
|
||||
import { copyToTheClipboard } from "../../utils/clipboard";
|
||||
|
@ -7,7 +7,7 @@
|
||||
// Dependencies
|
||||
import React, { Component } from "react";
|
||||
import classnames from "classnames";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
// Selectors
|
||||
import {
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import { showMenu } from "devtools-contextmenu";
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { Tab, Tabs, TabList, TabPanels } from "react-aria-components/src/tabs";
|
||||
import { formatKeyShortcut } from "../../utils/text";
|
||||
import actions from "../../actions";
|
||||
@ -22,14 +22,14 @@ import Outline from "./Outline";
|
||||
import SourcesTree from "./SourcesTree";
|
||||
|
||||
import type { SourcesMap } from "../../reducers/types";
|
||||
import type { SelectedPrimaryPaneTabType } from "../../reducers/ui";
|
||||
import type { SelectedPrimaryPaneTabType } from "../../selectors";
|
||||
|
||||
type State = {
|
||||
alphabetizeOutline: boolean
|
||||
};
|
||||
|
||||
type Props = {
|
||||
selectedTab: string,
|
||||
selectedTab: SelectedPrimaryPaneTabType,
|
||||
sources: SourcesMap,
|
||||
horizontal: boolean,
|
||||
sourceSearchOn: boolean,
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import actions from "../actions";
|
||||
|
||||
@ -157,20 +157,8 @@ export class ProjectSearch extends Component<Props, State> {
|
||||
);
|
||||
};
|
||||
|
||||
getResults = (): Result[] => {
|
||||
const { results } = this.props;
|
||||
return results
|
||||
.toJS()
|
||||
.map(result => ({
|
||||
type: "RESULT",
|
||||
...result,
|
||||
matches: result.matches.map(m => ({ type: "MATCH", ...m }))
|
||||
}))
|
||||
.filter(result => result.filepath && result.matches.length > 0);
|
||||
};
|
||||
|
||||
getResultCount = () =>
|
||||
this.getResults().reduce((count, file) => count + file.matches.length, 0);
|
||||
this.props.results.reduce((count, file) => count + file.matches.length, 0);
|
||||
|
||||
onKeyDown = (e: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Escape") {
|
||||
@ -271,8 +259,7 @@ export class ProjectSearch extends Component<Props, State> {
|
||||
};
|
||||
|
||||
renderResults = () => {
|
||||
const results = this.getResults();
|
||||
const { status } = this.props;
|
||||
const { status, results } = this.props;
|
||||
if (!this.props.query) {
|
||||
return;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../utils/connect";
|
||||
import fuzzyAldrin from "fuzzaldrin-plus";
|
||||
import { basename } from "../utils/path";
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
import { createSelector } from "reselect";
|
||||
import classnames from "classnames";
|
||||
|
||||
@ -28,8 +28,7 @@ import type {
|
||||
SourceLocation
|
||||
} from "../../../types";
|
||||
|
||||
type FormattedFrame = {
|
||||
...Frame,
|
||||
type FormattedFrame = Frame & {
|
||||
selectedLocation: SourceLocation
|
||||
};
|
||||
|
||||
@ -43,7 +42,7 @@ type Props = {
|
||||
breakpoint: FormattedBreakpoint,
|
||||
breakpoints: BreakpointType[],
|
||||
source: Source,
|
||||
frame: ?FormattedFrame,
|
||||
frame: FormattedFrame,
|
||||
enableBreakpoint: typeof actions.enableBreakpoint,
|
||||
removeBreakpoint: typeof actions.removeBreakpoint,
|
||||
removeBreakpoints: typeof actions.removeBreakpoints,
|
||||
@ -176,7 +175,7 @@ class Breakpoint extends PureComponent<Props> {
|
||||
const getFormattedFrame = createSelector(
|
||||
getSelectedSource,
|
||||
getSelectedFrame,
|
||||
(selectedSource: Source, frame: Frame) => {
|
||||
(selectedSource: Source, frame: Frame): ?FormattedFrame => {
|
||||
if (!frame) {
|
||||
return null;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
import actions from "../../../actions";
|
||||
import {
|
||||
getTruncatedFileName,
|
||||
@ -12,20 +12,32 @@ import {
|
||||
getSourceQueryString,
|
||||
getFileURL
|
||||
} from "../../../utils/source";
|
||||
import { getHasSiblingOfSameName } from "../../../selectors";
|
||||
import {
|
||||
getHasSiblingOfSameName,
|
||||
getBreakpointsForSource
|
||||
} from "../../../selectors";
|
||||
|
||||
import SourceIcon from "../../shared/SourceIcon";
|
||||
|
||||
import type { Source } from "../../../types";
|
||||
import type { Source, Breakpoint } from "../../../types";
|
||||
import showContextMenu from "./BreakpointHeadingsContextMenu";
|
||||
|
||||
type Props = {
|
||||
sources: Source[],
|
||||
source: Source,
|
||||
hasSiblingOfSameName: boolean,
|
||||
breakpointsForSource: Breakpoint[],
|
||||
disableBreakpointsInSource: typeof actions.disableBreakpointsInSource,
|
||||
enableBreakpointsInSource: typeof actions.enableBreakpointsInSource,
|
||||
removeBreakpointsInSource: typeof actions.removeBreakpointsInSource,
|
||||
selectSource: typeof actions.selectSource
|
||||
};
|
||||
|
||||
class BreakpointHeading extends PureComponent<Props> {
|
||||
onContextMenu = e => {
|
||||
showContextMenu({ ...this.props, contextMenuEvent: e });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { sources, source, hasSiblingOfSameName, selectSource } = this.props;
|
||||
|
||||
@ -37,6 +49,7 @@ class BreakpointHeading extends PureComponent<Props> {
|
||||
className="breakpoint-heading"
|
||||
title={getFileURL(source, false)}
|
||||
onClick={() => selectSource(source.id)}
|
||||
onContextMenu={this.onContextMenu}
|
||||
>
|
||||
<SourceIcon
|
||||
source={source}
|
||||
@ -52,10 +65,16 @@ class BreakpointHeading extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, { source }) => ({
|
||||
hasSiblingOfSameName: getHasSiblingOfSameName(state, source)
|
||||
hasSiblingOfSameName: getHasSiblingOfSameName(state, source),
|
||||
breakpointsForSource: getBreakpointsForSource(state, source.id)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ selectSource: actions.selectSource }
|
||||
{
|
||||
selectSource: actions.selectSource,
|
||||
enableBreakpointsInSource: actions.enableBreakpointsInSource,
|
||||
disableBreakpointsInSource: actions.disableBreakpointsInSource,
|
||||
removeBreakpointsInSource: actions.removeBreakpointsInSource
|
||||
}
|
||||
)(BreakpointHeading);
|
||||
|
@ -0,0 +1,90 @@
|
||||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import { buildMenu, showMenu } from "devtools-contextmenu";
|
||||
|
||||
import actions from "../../../actions";
|
||||
import type { Breakpoint, Source } from "../../../types";
|
||||
|
||||
type Props = {
|
||||
source: Source,
|
||||
breakpointsForSource: Breakpoint[],
|
||||
disableBreakpointsInSource: typeof actions.disableBreakpointsInSource,
|
||||
enableBreakpointsInSource: typeof actions.enableBreakpointsInSource,
|
||||
removeBreakpointsInSource: typeof actions.removeBreakpointsInSource,
|
||||
contextMenuEvent: SyntheticEvent<HTMLElement>
|
||||
};
|
||||
|
||||
export default function showContextMenu(props: Props) {
|
||||
const {
|
||||
source,
|
||||
breakpointsForSource,
|
||||
disableBreakpointsInSource,
|
||||
enableBreakpointsInSource,
|
||||
removeBreakpointsInSource,
|
||||
contextMenuEvent
|
||||
} = props;
|
||||
|
||||
contextMenuEvent.preventDefault();
|
||||
|
||||
const enableInSourceLabel = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.enableInSource.label"
|
||||
);
|
||||
const disableInSourceLabel = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.disableInSource.label"
|
||||
);
|
||||
const removeInSourceLabel = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.removeInSource.label"
|
||||
);
|
||||
const enableInSourceKey = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.enableInSource.accesskey"
|
||||
);
|
||||
const disableInSourceKey = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.disableInSource.accesskey"
|
||||
);
|
||||
const removeInSourceKey = L10N.getStr(
|
||||
"breakpointHeadingsMenuItem.removeInSource.accesskey"
|
||||
);
|
||||
|
||||
const disableInSourceItem = {
|
||||
id: "node-menu-disable-in-source",
|
||||
label: disableInSourceLabel,
|
||||
accesskey: disableInSourceKey,
|
||||
disabled: false,
|
||||
click: () => disableBreakpointsInSource(source)
|
||||
};
|
||||
|
||||
const enableInSourceItem = {
|
||||
id: "node-menu-enable-in-source",
|
||||
label: enableInSourceLabel,
|
||||
accesskey: enableInSourceKey,
|
||||
disabled: false,
|
||||
click: () => enableBreakpointsInSource(source)
|
||||
};
|
||||
|
||||
const removeInSourceItem = {
|
||||
id: "node-menu-enable-in-source",
|
||||
label: removeInSourceLabel,
|
||||
accesskey: removeInSourceKey,
|
||||
disabled: false,
|
||||
click: () => removeBreakpointsInSource(source)
|
||||
};
|
||||
|
||||
const hideDisableInSourceItem = breakpointsForSource.every(
|
||||
breakpoint => breakpoint.disabled
|
||||
);
|
||||
const hideEnableInSourceItem = breakpointsForSource.every(
|
||||
breakpoint => !breakpoint.disabled
|
||||
);
|
||||
|
||||
const items = [
|
||||
{ item: disableInSourceItem, hidden: () => hideDisableInSourceItem },
|
||||
{ item: enableInSourceItem, hidden: () => hideEnableInSourceItem },
|
||||
{ item: removeInSourceItem, hidden: () => false }
|
||||
];
|
||||
|
||||
showMenu(contextMenuEvent, buildMenu(items));
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
|
||||
import React, { Component } from "react";
|
||||
import classnames from "classnames";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
|
||||
import ExceptionOption from "./ExceptionOption";
|
||||
|
||||
|
@ -10,6 +10,7 @@ DIRS += [
|
||||
DebuggerModules(
|
||||
'Breakpoint.js',
|
||||
'BreakpointHeading.js',
|
||||
'BreakpointHeadingsContextMenu.js',
|
||||
'BreakpointsContextMenu.js',
|
||||
'ExceptionOption.js',
|
||||
'index.js',
|
||||
|
@ -8,7 +8,7 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from "react";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import { features } from "../../utils/prefs";
|
||||
import {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import { features } from "../../utils/prefs";
|
||||
import { objectInspector } from "devtools-reps";
|
||||
@ -164,6 +164,7 @@ class Expressions extends Component<Props, State> {
|
||||
hideInput = () => {
|
||||
this.setState({ focused: false });
|
||||
this.props.onExpressionAdded();
|
||||
this.props.clearExpressionError();
|
||||
};
|
||||
|
||||
onFocus = () => {
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../../utils/connect";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import type { Frame, Why } from "../../../types";
|
||||
@ -22,7 +22,6 @@ import { copyToTheClipboard } from "../../../utils/clipboard";
|
||||
import {
|
||||
getFrameworkGroupingState,
|
||||
getSelectedFrame,
|
||||
isPaused as getIsPaused,
|
||||
getCallStackFrames,
|
||||
getPauseReason
|
||||
} from "../../../selectors";
|
||||
@ -214,8 +213,7 @@ const mapStateToProps = state => ({
|
||||
frames: getCallStackFrames(state),
|
||||
why: getPauseReason(state),
|
||||
frameworkGroupingOn: getFrameworkGroupingState(state),
|
||||
selectedFrame: getSelectedFrame(state),
|
||||
pause: getIsPaused(state)
|
||||
selectedFrame: getSelectedFrame(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
@ -2,9 +2,8 @@
|
||||
* 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/>. */
|
||||
|
||||
// @flow
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import actions from "../../actions";
|
||||
|
||||
import { createObjectClient } from "../../client/firefox";
|
||||
@ -13,7 +12,7 @@ import { getSelectedFrame, getAllPopupObjectProperties } from "../../selectors";
|
||||
import { objectInspector } from "devtools-reps";
|
||||
import { isReactComponent } from "../../utils/preview";
|
||||
|
||||
import type { Frame, Grip } from "../../types";
|
||||
import type { Frame } from "../../types";
|
||||
|
||||
const {
|
||||
component: ObjectInspector,
|
||||
@ -28,7 +27,7 @@ type Props = {
|
||||
selectedFrame: Frame,
|
||||
popupObjectProperties: Object,
|
||||
setPopupObjectProperties: typeof actions.setPopupObjectProperties,
|
||||
openElementInInspector: (grip: Grip) => void
|
||||
openElementInInspector: typeof actions.setPopupObjectProperties
|
||||
};
|
||||
|
||||
class FrameworkComponent extends PureComponent<Props> {
|
||||
@ -99,13 +98,13 @@ class FrameworkComponent extends PureComponent<Props> {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedFrame: getSelectedFrame(state),
|
||||
popupObjectProperties: getAllPopupObjectProperties(state),
|
||||
openElementInInspector: actions.openElementInInspectorCommand
|
||||
popupObjectProperties: getAllPopupObjectProperties(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
setPopupObjectProperties: actions.setPopupObjectProperties
|
||||
setPopupObjectProperties: actions.setPopupObjectProperties,
|
||||
openElementInInspector: actions.openElementInInspectorCommand
|
||||
}
|
||||
)(FrameworkComponent);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import actions from "../../actions";
|
||||
import { createObjectClient } from "../../client/firefox";
|
||||
|
||||
@ -19,7 +19,8 @@ import {
|
||||
import { getScopes } from "../../utils/pause/scopes";
|
||||
|
||||
import { objectInspector } from "devtools-reps";
|
||||
import type { Pause, Why } from "../../types";
|
||||
|
||||
import type { Why } from "../../types";
|
||||
import type { NamedValue } from "../../utils/pause/scopes/types";
|
||||
|
||||
import "./Scopes.css";
|
||||
@ -27,7 +28,7 @@ import "./Scopes.css";
|
||||
const { ObjectInspector } = objectInspector;
|
||||
|
||||
type Props = {
|
||||
isPaused: Pause,
|
||||
isPaused: boolean,
|
||||
selectedFrame: Object,
|
||||
generatedFrameScopes: Object,
|
||||
originalFrameScopes: Object | null,
|
||||
|
@ -2,25 +2,54 @@
|
||||
* 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/>. */
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "../../utils/connect";
|
||||
import type { List } from "immutable";
|
||||
|
||||
import "./Workers.css";
|
||||
|
||||
import actions from "../../actions";
|
||||
import { getWorkers } from "../../selectors";
|
||||
import {
|
||||
getMainThread,
|
||||
getCurrentThread,
|
||||
threadIsPaused,
|
||||
getWorkers
|
||||
} from "../../selectors";
|
||||
import { basename } from "../../utils/path";
|
||||
import { features } from "../../utils/prefs";
|
||||
import type { Worker } from "../../types";
|
||||
import AccessibleImage from "../shared/AccessibleImage";
|
||||
import classnames from "classnames";
|
||||
|
||||
export class Workers extends PureComponent {
|
||||
type Props = {
|
||||
selectThread: string => void
|
||||
};
|
||||
|
||||
export class Workers extends Component<Props> {
|
||||
props: {
|
||||
workers: List<Worker>,
|
||||
openWorkerToolbox: object => void
|
||||
openWorkerToolbox: object => void,
|
||||
mainThread: string,
|
||||
currentThread: string
|
||||
};
|
||||
|
||||
renderWorkers(workers) {
|
||||
renderWorkers(workers, mainThread, currentThread) {
|
||||
if (features.windowlessWorkers) {
|
||||
return [{ actor: mainThread }, ...workers].map(worker => (
|
||||
<div
|
||||
className={classnames(
|
||||
"worker",
|
||||
worker.actor == currentThread && "selected"
|
||||
)}
|
||||
key={worker.actor}
|
||||
onClick={() => this.props.selectThread(worker.actor)}
|
||||
>
|
||||
<img className="domain" />
|
||||
{(worker.url ? basename(worker.url) : "Main Thread") +
|
||||
(this.props.threadIsPaused(worker.actor) ? " PAUSED" : "")}
|
||||
</div>
|
||||
));
|
||||
}
|
||||
const { openWorkerToolbox } = this.props;
|
||||
return workers.map(worker => (
|
||||
<div
|
||||
@ -39,11 +68,11 @@ export class Workers extends PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { workers } = this.props;
|
||||
const { workers, mainThread, currentThread } = this.props;
|
||||
return (
|
||||
<div className="pane workers-list">
|
||||
{workers && workers.size > 0
|
||||
? this.renderWorkers(workers)
|
||||
? this.renderWorkers(workers, mainThread, currentThread)
|
||||
: this.renderNoWorkersPlaceholder()}
|
||||
</div>
|
||||
);
|
||||
@ -51,10 +80,16 @@ export class Workers extends PureComponent {
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
workers: getWorkers(state)
|
||||
workers: getWorkers(state),
|
||||
mainThread: getMainThread(state),
|
||||
currentThread: getCurrentThread(state),
|
||||
threadIsPaused: thread => threadIsPaused(state, thread)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actions
|
||||
{
|
||||
openWorkerToolbox: actions.openWorkerToolbox,
|
||||
selectThread: actions.selectThread
|
||||
}
|
||||
)(Workers);
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import classnames from "classnames";
|
||||
import actions from "../../actions";
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { List } from "immutable";
|
||||
|
||||
import actions from "../../actions";
|
||||
@ -18,8 +18,7 @@ import {
|
||||
getIsWaitingOnBreak,
|
||||
getShouldPauseOnExceptions,
|
||||
getShouldPauseOnCaughtExceptions,
|
||||
getWorkers,
|
||||
getExtra
|
||||
getWorkers
|
||||
} from "../../selectors";
|
||||
|
||||
import Svg from "../shared/Svg";
|
||||
@ -33,7 +32,6 @@ import Workers from "./Workers";
|
||||
import Accordion from "../shared/Accordion";
|
||||
import CommandBar from "./CommandBar";
|
||||
import UtilsBar from "./UtilsBar";
|
||||
import FrameworkComponent from "./FrameworkComponent";
|
||||
import XHRBreakpoints from "./XHRBreakpoints";
|
||||
|
||||
import Scopes from "./Scopes";
|
||||
@ -72,7 +70,6 @@ type State = {
|
||||
|
||||
type Props = {
|
||||
expressions: List<Expression>,
|
||||
extra: Object,
|
||||
hasFrames: boolean,
|
||||
horizontal: boolean,
|
||||
breakpoints: Object,
|
||||
@ -216,22 +213,6 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
getComponentItem() {
|
||||
const {
|
||||
extra: { react }
|
||||
} = this.props;
|
||||
|
||||
return {
|
||||
header: react.displayName,
|
||||
className: "component-pane",
|
||||
component: <FrameworkComponent />,
|
||||
opened: prefs.componentVisible,
|
||||
onToggle: opened => {
|
||||
prefs.componentVisible = opened;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getWatchItem(): AccordionPaneItem {
|
||||
return {
|
||||
header: L10N.getStr("watchExpressions.header"),
|
||||
@ -318,7 +299,7 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
}
|
||||
|
||||
getStartItems() {
|
||||
const { extra, workers } = this.props;
|
||||
const { workers } = this.props;
|
||||
|
||||
const items: Array<AccordionPaneItem> = [];
|
||||
if (this.props.horizontal) {
|
||||
@ -335,10 +316,6 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
items.push(this.getCallStackItem());
|
||||
|
||||
if (this.props.horizontal) {
|
||||
if (features.componentPane && extra && extra.react) {
|
||||
items.push(this.getComponentItem());
|
||||
}
|
||||
|
||||
items.push(this.getScopeItem());
|
||||
}
|
||||
}
|
||||
@ -355,7 +332,7 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
}
|
||||
|
||||
getEndItems() {
|
||||
const { extra, workers } = this.props;
|
||||
const { workers } = this.props;
|
||||
|
||||
let items: Array<AccordionPaneItem> = [];
|
||||
|
||||
@ -369,10 +346,6 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
|
||||
items.push(this.getWatchItem());
|
||||
|
||||
if (features.componentPane && extra && extra.react) {
|
||||
items.push(this.getComponentItem());
|
||||
}
|
||||
|
||||
if (this.props.hasFrames) {
|
||||
items = [...items, this.getScopeItem()];
|
||||
}
|
||||
@ -427,7 +400,6 @@ class SecondaryPanes extends Component<Props, State> {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
expressions: getExpressions(state),
|
||||
extra: getExtra(state),
|
||||
hasFrames: !!getTopFrame(state),
|
||||
breakpoints: getBreakpointsList(state),
|
||||
breakpointsDisabled: getBreakpointsDisabled(state),
|
||||
|
@ -11,7 +11,6 @@ DIRS += [
|
||||
DebuggerModules(
|
||||
'CommandBar.js',
|
||||
'Expressions.js',
|
||||
'FrameworkComponent.js',
|
||||
'index.js',
|
||||
'Scopes.js',
|
||||
'UtilsBar.js',
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
import React, { Component } from "react";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../utils/connect";
|
||||
|
||||
import actions from "../actions";
|
||||
import { getPaneCollapse } from "../selectors";
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
import AccessibleImage from "./AccessibleImage";
|
||||
|
||||
|
@ -13,15 +13,10 @@ import * as I from "immutable";
|
||||
import makeRecord from "../utils/makeRecord";
|
||||
import { findEmptyLines } from "../utils/ast";
|
||||
|
||||
import type {
|
||||
AstLocation,
|
||||
SymbolDeclarations,
|
||||
PausePoints,
|
||||
PausePoint
|
||||
} from "../workers/parser";
|
||||
import type { AstLocation, SymbolDeclarations } from "../workers/parser";
|
||||
|
||||
import type { Map } from "immutable";
|
||||
import type { SourceLocation, Source } from "../types";
|
||||
import type { SourceLocation, Source, Position } from "../types";
|
||||
import type { Action, DonePromiseAction } from "../actions/types";
|
||||
import type { Record } from "../utils/makeRecord";
|
||||
|
||||
@ -36,7 +31,18 @@ export type SourceMetaDataType = {
|
||||
};
|
||||
|
||||
export type SourceMetaDataMap = Map<string, SourceMetaDataType>;
|
||||
export type PausePointsMap = Map<string, PausePoints>;
|
||||
|
||||
export type PausePoint = {
|
||||
location: Position,
|
||||
generatedLocation: SourceLocation,
|
||||
types: { break: boolean, step: boolean }
|
||||
};
|
||||
|
||||
export type PausePointsMap = {
|
||||
[line: string]: { [column: string]: PausePoint }
|
||||
};
|
||||
export type PausePoints = PausePoint[];
|
||||
export type PausePointsState = Map<string, PausePoint[]>;
|
||||
|
||||
export type Preview =
|
||||
| {| updating: true |}
|
||||
@ -47,8 +53,7 @@ export type Preview =
|
||||
location: AstLocation,
|
||||
cursorPos: any,
|
||||
tokenPos: AstLocation,
|
||||
result: Object,
|
||||
extra: Object
|
||||
result: Object
|
||||
|};
|
||||
|
||||
export type ASTState = {
|
||||
@ -57,22 +62,20 @@ export type ASTState = {
|
||||
outOfScopeLocations: ?Array<AstLocation>,
|
||||
inScopeLines: ?Array<Number>,
|
||||
preview: Preview,
|
||||
pausePoints: PausePointsMap,
|
||||
pausePoints: PausePointsState,
|
||||
sourceMetaData: SourceMetaDataMap
|
||||
};
|
||||
|
||||
export function initialASTState() {
|
||||
return makeRecord(
|
||||
({
|
||||
symbols: I.Map(),
|
||||
emptyLines: I.Map(),
|
||||
outOfScopeLocations: null,
|
||||
inScopeLines: null,
|
||||
preview: null,
|
||||
pausePoints: I.Map(),
|
||||
sourceMetaData: I.Map()
|
||||
}: ASTState)
|
||||
)();
|
||||
export function initialASTState(): Record<ASTState> {
|
||||
return makeRecord({
|
||||
symbols: I.Map(),
|
||||
emptyLines: I.Map(),
|
||||
outOfScopeLocations: null,
|
||||
inScopeLines: null,
|
||||
preview: null,
|
||||
pausePoints: I.Map(),
|
||||
sourceMetaData: I.Map()
|
||||
})();
|
||||
}
|
||||
|
||||
function update(
|
||||
@ -221,12 +224,35 @@ export function getPausePoint(
|
||||
return;
|
||||
}
|
||||
|
||||
const linePoints = pausePoints[String(line)];
|
||||
if (linePoints && column) {
|
||||
return linePoints[String(column)];
|
||||
for (const point of pausePoints) {
|
||||
const { location: pointLocation } = point;
|
||||
if (pointLocation.line == line && pointLocation.column == column) {
|
||||
return point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getFirstPausePointLocation(
|
||||
state: OuterState,
|
||||
location: SourceLocation
|
||||
): SourceLocation {
|
||||
const { sourceId } = location;
|
||||
const pausePoints = getPausePoints(state, location.sourceId);
|
||||
if (!pausePoints) {
|
||||
return location;
|
||||
}
|
||||
|
||||
const pausesAtLine = pausePoints[location.line];
|
||||
if (pausesAtLine) {
|
||||
const values: PausePoint[] = (Object.values(pausesAtLine): any);
|
||||
const firstPausePoint = values.find(pausePoint => pausePoint.types.break);
|
||||
if (firstPausePoint) {
|
||||
return { ...firstPausePoint.location, sourceId };
|
||||
}
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
export function hasPausePoints(state: OuterState, sourceId: string): boolean {
|
||||
const pausePoints = getPausePoints(state, sourceId);
|
||||
return !!pausePoints;
|
||||
|
@ -21,11 +21,9 @@ type DebuggeeState = {
|
||||
workers: WorkersList
|
||||
};
|
||||
|
||||
export const createDebuggeeState = makeRecord(
|
||||
({
|
||||
workers: List()
|
||||
}: DebuggeeState)
|
||||
);
|
||||
export const createDebuggeeState: () => Record<DebuggeeState> = makeRecord({
|
||||
workers: List()
|
||||
});
|
||||
|
||||
export default function debuggee(
|
||||
state: Record<DebuggeeState> = createDebuggeeState(),
|
||||
|
@ -13,7 +13,7 @@ import makeRecord from "../utils/makeRecord";
|
||||
import { List, Map } from "immutable";
|
||||
import { omit, zip } from "lodash";
|
||||
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import { prefs } from "../utils/prefs";
|
||||
|
||||
import type { Expression } from "../types";
|
||||
@ -27,14 +27,12 @@ export type ExpressionState = {
|
||||
currentAutocompleteInput: string | null
|
||||
};
|
||||
|
||||
export const createExpressionState = makeRecord(
|
||||
({
|
||||
expressions: List(restoreExpressions()),
|
||||
expressionError: false,
|
||||
autocompleteMatches: Map({}),
|
||||
currentAutocompleteInput: null
|
||||
}: ExpressionState)
|
||||
);
|
||||
export const createExpressionState: () => Record<ExpressionState> = makeRecord({
|
||||
expressions: List(restoreExpressions()),
|
||||
expressionError: false,
|
||||
autocompleteMatches: Map({}),
|
||||
currentAutocompleteInput: null
|
||||
});
|
||||
|
||||
function update(
|
||||
state: Record<ExpressionState> = createExpressionState(),
|
||||
|
@ -46,17 +46,15 @@ const emptySearchResults = Object.freeze({
|
||||
count: 0
|
||||
});
|
||||
|
||||
export const createFileSearchState = makeRecord(
|
||||
({
|
||||
query: "",
|
||||
searchResults: emptySearchResults,
|
||||
modifiers: makeRecord({
|
||||
caseSensitive: prefs.fileSearchCaseSensitive,
|
||||
wholeWord: prefs.fileSearchWholeWord,
|
||||
regexMatch: prefs.fileSearchRegexMatch
|
||||
})()
|
||||
}: FileSearchState)
|
||||
);
|
||||
export const createFileSearchState: () => Record<FileSearchState> = makeRecord({
|
||||
query: "",
|
||||
searchResults: emptySearchResults,
|
||||
modifiers: makeRecord({
|
||||
caseSensitive: prefs.fileSearchCaseSensitive,
|
||||
wholeWord: prefs.fileSearchWholeWord,
|
||||
regexMatch: prefs.fileSearchRegexMatch
|
||||
})()
|
||||
});
|
||||
|
||||
function update(
|
||||
state: Record<FileSearchState> = createFileSearchState(),
|
||||
|
@ -10,7 +10,7 @@
|
||||
* @module reducers/pause
|
||||
*/
|
||||
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import { isGeneratedId } from "devtools-source-map";
|
||||
import { prefs } from "../utils/prefs";
|
||||
import { getSelectedSource } from "./sources";
|
||||
@ -32,8 +32,8 @@ export type Command =
|
||||
| "reverseStepOut"
|
||||
| "expression";
|
||||
|
||||
export type PauseState = {
|
||||
extra: ?Object,
|
||||
// Pause state associated with an individual thread.
|
||||
type ThreadPauseState = {
|
||||
why: ?Why,
|
||||
isWaitingOnBreak: boolean,
|
||||
frames: ?(any[]),
|
||||
@ -60,27 +60,29 @@ export type PauseState = {
|
||||
loadedObjects: Object,
|
||||
shouldPauseOnExceptions: boolean,
|
||||
shouldPauseOnCaughtExceptions: boolean,
|
||||
canRewind: boolean,
|
||||
debuggeeUrl: string,
|
||||
command: Command,
|
||||
previousLocation: ?MappedLocation,
|
||||
skipPausing: boolean
|
||||
};
|
||||
|
||||
// Pause state describing all threads.
|
||||
export type PauseState = {
|
||||
mainThread: string,
|
||||
currentThread: string,
|
||||
debuggeeUrl: string,
|
||||
canRewind: boolean,
|
||||
threads: { [string]: ThreadPauseState }
|
||||
};
|
||||
|
||||
export const createPauseState = (): PauseState => ({
|
||||
...emptyPauseState,
|
||||
extra: {},
|
||||
isWaitingOnBreak: false,
|
||||
shouldPauseOnExceptions: prefs.pauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions: prefs.pauseOnCaughtExceptions,
|
||||
mainThread: "UnknownThread",
|
||||
currentThread: "UnknownThread",
|
||||
threads: {},
|
||||
canRewind: false,
|
||||
debuggeeUrl: "",
|
||||
command: null,
|
||||
previousLocation: null,
|
||||
skipPausing: prefs.skipPausing
|
||||
debuggeeUrl: ""
|
||||
});
|
||||
|
||||
const emptyPauseState = {
|
||||
const resumedPauseState = {
|
||||
frames: null,
|
||||
frameScopes: {
|
||||
generated: {},
|
||||
@ -92,13 +94,56 @@ const emptyPauseState = {
|
||||
why: null
|
||||
};
|
||||
|
||||
const createInitialPauseState = () => ({
|
||||
...resumedPauseState,
|
||||
isWaitingOnBreak: false,
|
||||
shouldPauseOnExceptions: prefs.pauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions: prefs.pauseOnCaughtExceptions,
|
||||
canRewind: false,
|
||||
debuggeeUrl: "",
|
||||
command: null,
|
||||
previousLocation: null,
|
||||
skipPausing: prefs.skipPausing
|
||||
});
|
||||
|
||||
function getThreadPauseState(state: PauseState, thread: string) {
|
||||
// Thread state is lazily initialized so that we don't have to keep track of
|
||||
// the current set of worker threads.
|
||||
return state.threads[thread] || createInitialPauseState();
|
||||
}
|
||||
|
||||
function update(
|
||||
state: PauseState = createPauseState(),
|
||||
action: Action
|
||||
): PauseState {
|
||||
// Actions need to specify any thread they are operating on. These helpers
|
||||
// manage updating the pause state for that thread.
|
||||
const threadState = () => {
|
||||
if (!action.thread) {
|
||||
throw new Error(`Missing thread in action ${action.type}`);
|
||||
}
|
||||
return getThreadPauseState(state, action.thread);
|
||||
};
|
||||
|
||||
const updateThreadState = newThreadState => {
|
||||
if (!action.thread) {
|
||||
throw new Error(`Missing thread in action ${action.type}`);
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
threads: {
|
||||
...state.threads,
|
||||
[action.thread]: { ...threadState(), ...newThreadState }
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
switch (action.type) {
|
||||
case "SELECT_THREAD":
|
||||
return { ...state, currentThread: action.thread };
|
||||
|
||||
case "PAUSED": {
|
||||
const { selectedFrameId, frames, loadedObjects, why } = action;
|
||||
const { thread, selectedFrameId, frames, loadedObjects, why } = action;
|
||||
|
||||
// turn this into an object keyed by object id
|
||||
const objectMap = {};
|
||||
@ -106,24 +151,20 @@ function update(
|
||||
objectMap[obj.value.objectId] = obj;
|
||||
});
|
||||
|
||||
return {
|
||||
...state,
|
||||
state = { ...state, currentThread: thread };
|
||||
return updateThreadState({
|
||||
isWaitingOnBreak: false,
|
||||
selectedFrameId,
|
||||
frames,
|
||||
frameScopes: { ...emptyPauseState.frameScopes },
|
||||
frameScopes: { ...resumedPauseState.frameScopes },
|
||||
loadedObjects: objectMap,
|
||||
why
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
case "MAP_FRAMES": {
|
||||
const { selectedFrameId, frames } = action;
|
||||
return { ...state, frames, selectedFrameId };
|
||||
}
|
||||
|
||||
case "ADD_EXTRA": {
|
||||
return { ...state, extra: action.extra };
|
||||
return updateThreadState({ frames, selectedFrameId });
|
||||
}
|
||||
|
||||
case "ADD_SCOPES": {
|
||||
@ -131,33 +172,30 @@ function update(
|
||||
const selectedFrameId = frame.id;
|
||||
|
||||
const generated = {
|
||||
...state.frameScopes.generated,
|
||||
...threadState().frameScopes.generated,
|
||||
[selectedFrameId]: {
|
||||
pending: status !== "done",
|
||||
scope: value
|
||||
}
|
||||
};
|
||||
return {
|
||||
...state,
|
||||
|
||||
return updateThreadState({
|
||||
frameScopes: {
|
||||
...state.frameScopes,
|
||||
...threadState().frameScopes,
|
||||
generated
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
case "TRAVEL_TO":
|
||||
return {
|
||||
...state,
|
||||
...action.data.paused
|
||||
};
|
||||
return updateThreadState({ ...action.data.paused });
|
||||
|
||||
case "MAP_SCOPES": {
|
||||
const { frame, status, value } = action;
|
||||
const selectedFrameId = frame.id;
|
||||
|
||||
const original = {
|
||||
...state.frameScopes.original,
|
||||
...threadState().frameScopes.original,
|
||||
[selectedFrameId]: {
|
||||
pending: status !== "done",
|
||||
scope: value && value.scope
|
||||
@ -165,49 +203,48 @@ function update(
|
||||
};
|
||||
|
||||
const mappings = {
|
||||
...state.frameScopes.mappings,
|
||||
...threadState().frameScopes.mappings,
|
||||
[selectedFrameId]: value && value.mappings
|
||||
};
|
||||
return {
|
||||
...state,
|
||||
|
||||
return updateThreadState({
|
||||
frameScopes: {
|
||||
...state.frameScopes,
|
||||
...threadState().frameScopes,
|
||||
original,
|
||||
mappings
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
case "BREAK_ON_NEXT":
|
||||
return { ...state, isWaitingOnBreak: true };
|
||||
return updateThreadState({ isWaitingOnBreak: true });
|
||||
|
||||
case "SELECT_FRAME":
|
||||
return {
|
||||
...state,
|
||||
selectedFrameId: action.frame.id
|
||||
};
|
||||
return updateThreadState({ selectedFrameId: action.frame.id });
|
||||
|
||||
case "SET_POPUP_OBJECT_PROPERTIES":
|
||||
case "SET_POPUP_OBJECT_PROPERTIES": {
|
||||
if (!action.properties) {
|
||||
return { ...state };
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
return updateThreadState({
|
||||
loadedObjects: {
|
||||
...state.loadedObjects,
|
||||
...threadState().loadedObjects,
|
||||
[action.objectId]: action.properties
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
case "CONNECT":
|
||||
return {
|
||||
...createPauseState(),
|
||||
mainThread: action.thread,
|
||||
currentThread: action.thread,
|
||||
debuggeeUrl: action.url,
|
||||
canRewind: action.canRewind
|
||||
};
|
||||
|
||||
case "PAUSE_ON_EXCEPTIONS":
|
||||
case "PAUSE_ON_EXCEPTIONS": {
|
||||
const { shouldPauseOnExceptions, shouldPauseOnCaughtExceptions } = action;
|
||||
|
||||
prefs.pauseOnExceptions = shouldPauseOnExceptions;
|
||||
@ -216,40 +253,52 @@ function update(
|
||||
// Preserving for the old debugger
|
||||
prefs.ignoreCaughtExceptions = !shouldPauseOnCaughtExceptions;
|
||||
|
||||
return {
|
||||
...state,
|
||||
return updateThreadState({
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions
|
||||
};
|
||||
|
||||
case "COMMAND": {
|
||||
return action.status === "start"
|
||||
? {
|
||||
...state,
|
||||
...emptyPauseState,
|
||||
command: action.command,
|
||||
previousLocation: getPauseLocation(state, action)
|
||||
}
|
||||
: { ...state, command: null };
|
||||
});
|
||||
}
|
||||
|
||||
case "COMMAND":
|
||||
if (action.status === "start") {
|
||||
return updateThreadState({
|
||||
...resumedPauseState,
|
||||
command: action.command,
|
||||
previousLocation: getPauseLocation(threadState(), action)
|
||||
});
|
||||
}
|
||||
return updateThreadState({ command: null });
|
||||
|
||||
case "RESUME":
|
||||
return { ...state, ...emptyPauseState };
|
||||
// Workaround for threads resuming before the initial connection.
|
||||
if (!action.thread && !state.currentThread) {
|
||||
return state;
|
||||
}
|
||||
return updateThreadState(resumedPauseState);
|
||||
|
||||
case "EVALUATE_EXPRESSION":
|
||||
return {
|
||||
...state,
|
||||
return updateThreadState({
|
||||
command: action.status === "start" ? "expression" : null
|
||||
};
|
||||
});
|
||||
|
||||
case "NAVIGATE":
|
||||
return { ...state, ...emptyPauseState, debuggeeUrl: action.url };
|
||||
return {
|
||||
...state,
|
||||
currentThread: state.mainThread,
|
||||
threads: {
|
||||
[state.mainThread]: {
|
||||
...state.threads[state.mainThread],
|
||||
...resumedPauseState
|
||||
}
|
||||
},
|
||||
debuggeeUrl: action.url
|
||||
};
|
||||
|
||||
case "TOGGLE_SKIP_PAUSING": {
|
||||
const { skipPausing } = action;
|
||||
prefs.skipPausing = skipPausing;
|
||||
|
||||
return { ...state, skipPausing };
|
||||
return updateThreadState({ skipPausing });
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,25 +336,39 @@ function getPauseLocation(state, action) {
|
||||
// (right now) to type those wrapped functions.
|
||||
type OuterState = State;
|
||||
|
||||
const getPauseState = state => state.pause;
|
||||
function getCurrentPauseState(state: OuterState): ThreadPauseState {
|
||||
return getThreadPauseState(state.pause, state.pause.currentThread);
|
||||
}
|
||||
|
||||
export const getAllPopupObjectProperties = createSelector(
|
||||
getPauseState,
|
||||
getCurrentPauseState,
|
||||
pauseWrapper => pauseWrapper.loadedObjects
|
||||
);
|
||||
|
||||
export function getPauseReason(state: OuterState): ?Why {
|
||||
return state.pause.why;
|
||||
return getCurrentPauseState(state).why;
|
||||
}
|
||||
|
||||
export function getPauseCommand(state: OuterState): Command {
|
||||
return state.pause && state.pause.command;
|
||||
return getCurrentPauseState(state).command;
|
||||
}
|
||||
|
||||
export function isStepping(state: OuterState) {
|
||||
return ["stepIn", "stepOver", "stepOut"].includes(getPauseCommand(state));
|
||||
}
|
||||
|
||||
export function getMainThread(state: OuterState) {
|
||||
return state.pause.mainThread;
|
||||
}
|
||||
|
||||
export function getCurrentThread(state: OuterState) {
|
||||
return state.pause.currentThread;
|
||||
}
|
||||
|
||||
export function threadIsPaused(state: OuterState, thread: string) {
|
||||
return !!getThreadPauseState(state.pause, thread).frames;
|
||||
}
|
||||
|
||||
export function isPaused(state: OuterState) {
|
||||
return !!getFrames(state);
|
||||
}
|
||||
@ -315,11 +378,11 @@ export function getIsPaused(state: OuterState) {
|
||||
}
|
||||
|
||||
export function getPreviousPauseFrameLocation(state: OuterState) {
|
||||
return state.pause.previousLocation;
|
||||
return getCurrentPauseState(state).previousLocation;
|
||||
}
|
||||
|
||||
export function isEvaluatingExpression(state: OuterState) {
|
||||
return state.pause.command === "expression";
|
||||
return getCurrentPauseState(state).command === "expression";
|
||||
}
|
||||
|
||||
export function getPopupObjectProperties(state: OuterState, objectId: string) {
|
||||
@ -327,27 +390,23 @@ export function getPopupObjectProperties(state: OuterState, objectId: string) {
|
||||
}
|
||||
|
||||
export function getIsWaitingOnBreak(state: OuterState) {
|
||||
return state.pause.isWaitingOnBreak;
|
||||
return getCurrentPauseState(state).isWaitingOnBreak;
|
||||
}
|
||||
|
||||
export function getShouldPauseOnExceptions(state: OuterState) {
|
||||
return state.pause.shouldPauseOnExceptions;
|
||||
return getCurrentPauseState(state).shouldPauseOnExceptions;
|
||||
}
|
||||
|
||||
export function getShouldPauseOnCaughtExceptions(state: OuterState) {
|
||||
return state.pause.shouldPauseOnCaughtExceptions;
|
||||
return getCurrentPauseState(state).shouldPauseOnCaughtExceptions;
|
||||
}
|
||||
|
||||
export function getCanRewind(state: OuterState) {
|
||||
return state.pause.canRewind;
|
||||
}
|
||||
|
||||
export function getExtra(state: OuterState) {
|
||||
return state.pause.extra;
|
||||
}
|
||||
|
||||
export function getFrames(state: OuterState) {
|
||||
return state.pause.frames;
|
||||
return getCurrentPauseState(state).frames;
|
||||
}
|
||||
|
||||
function getGeneratedFrameId(frameId: string): string {
|
||||
@ -389,7 +448,7 @@ export function getOriginalFrameScope(
|
||||
}
|
||||
|
||||
export function getFrameScopes(state: OuterState) {
|
||||
return state.pause.frameScopes;
|
||||
return getCurrentPauseState(state).frameScopes;
|
||||
}
|
||||
|
||||
export function getSelectedFrameBindings(state: OuterState) {
|
||||
@ -467,7 +526,7 @@ export function getSelectedScopeMappings(
|
||||
}
|
||||
|
||||
export function getSelectedFrameId(state: OuterState) {
|
||||
return state.pause.selectedFrameId;
|
||||
return getCurrentPauseState(state).selectedFrameId;
|
||||
}
|
||||
|
||||
export function getTopFrame(state: OuterState) {
|
||||
@ -492,7 +551,7 @@ export function getDebuggeeUrl(state: OuterState) {
|
||||
}
|
||||
|
||||
export function getSkipPausing(state: OuterState) {
|
||||
return state.pause.skipPausing;
|
||||
return getCurrentPauseState(state).skipPausing;
|
||||
}
|
||||
|
||||
// NOTE: currently only used for chrome
|
||||
|
@ -10,17 +10,12 @@
|
||||
* @module reducers/project-text-search
|
||||
*/
|
||||
|
||||
import * as I from "immutable";
|
||||
import makeRecord from "../utils/makeRecord";
|
||||
|
||||
import type { Action } from "../actions/types";
|
||||
import type { Record } from "../utils/makeRecord";
|
||||
import type { List } from "immutable";
|
||||
|
||||
export type Search = {
|
||||
id: string,
|
||||
filepath: string,
|
||||
matches: I.List<any>
|
||||
+sourceId: string,
|
||||
+filepath: string,
|
||||
+matches: any[]
|
||||
};
|
||||
export type StatusType = "INITIAL" | "FETCHING" | "DONE" | "ERROR";
|
||||
export const statusType = {
|
||||
@ -30,77 +25,75 @@ export const statusType = {
|
||||
error: "ERROR"
|
||||
};
|
||||
|
||||
export type ResultRecord = Record<Search>;
|
||||
export type ResultList = List<ResultRecord>;
|
||||
export type ResultList = Search[];
|
||||
export type ProjectTextSearchState = {
|
||||
query: string,
|
||||
results: ResultList,
|
||||
status: string
|
||||
+query: string,
|
||||
+results: ResultList,
|
||||
+status: string
|
||||
};
|
||||
|
||||
export function initialProjectTextSearchState(): Record<
|
||||
ProjectTextSearchState
|
||||
> {
|
||||
return makeRecord(
|
||||
({
|
||||
query: "",
|
||||
results: I.List(),
|
||||
status: statusType.initial
|
||||
}: ProjectTextSearchState)
|
||||
)();
|
||||
export function initialProjectTextSearchState(): ProjectTextSearchState {
|
||||
return {
|
||||
query: "",
|
||||
results: [],
|
||||
status: statusType.initial
|
||||
};
|
||||
}
|
||||
|
||||
function update(
|
||||
state: Record<ProjectTextSearchState> = initialProjectTextSearchState(),
|
||||
state: ProjectTextSearchState = initialProjectTextSearchState(),
|
||||
action: Action
|
||||
): Record<ProjectTextSearchState> {
|
||||
): ProjectTextSearchState {
|
||||
switch (action.type) {
|
||||
case "ADD_QUERY":
|
||||
const actionCopy = action;
|
||||
return state.update("query", value => actionCopy.query);
|
||||
return { ...state, query: action.query };
|
||||
|
||||
case "CLEAR_QUERY":
|
||||
return state.merge({
|
||||
return {
|
||||
...state,
|
||||
query: "",
|
||||
status: statusType.initial
|
||||
});
|
||||
};
|
||||
|
||||
case "ADD_SEARCH_RESULT":
|
||||
const results = state.get("results");
|
||||
return state.merge({ results: results.push(action.result) });
|
||||
const results = state.results;
|
||||
if (action.result.matches.length === 0) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const result = {
|
||||
type: "RESULT",
|
||||
...action.result,
|
||||
matches: action.result.matches.map(m => ({ type: "MATCH", ...m }))
|
||||
};
|
||||
return { ...state, results: [...results, result] };
|
||||
|
||||
case "UPDATE_STATUS":
|
||||
return state.merge({ status: action.status });
|
||||
return { ...state, status: action.status };
|
||||
|
||||
case "CLEAR_SEARCH_RESULTS":
|
||||
return state.merge({
|
||||
results: state.get("results").clear()
|
||||
});
|
||||
return { ...state, results: [] };
|
||||
|
||||
case "CLEAR_SEARCH":
|
||||
case "CLOSE_PROJECT_SEARCH":
|
||||
case "NAVIGATE":
|
||||
return state.merge({
|
||||
query: "",
|
||||
results: state.get("results").clear(),
|
||||
status: statusType.initial
|
||||
});
|
||||
return initialProjectTextSearchState();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
type OuterState = { projectTextSearch: Record<ProjectTextSearchState> };
|
||||
type OuterState = { projectTextSearch: ProjectTextSearchState };
|
||||
|
||||
export function getTextSearchResults(state: OuterState) {
|
||||
return state.projectTextSearch.get("results");
|
||||
return state.projectTextSearch.results;
|
||||
}
|
||||
|
||||
export function getTextSearchStatus(state: OuterState) {
|
||||
return state.projectTextSearch.get("status");
|
||||
return state.projectTextSearch.status;
|
||||
}
|
||||
|
||||
export function getTextSearchQuery(state: OuterState) {
|
||||
return state.projectTextSearch.get("query");
|
||||
return state.projectTextSearch.query;
|
||||
}
|
||||
|
||||
export default update;
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @module reducers/sources
|
||||
*/
|
||||
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import {
|
||||
getPrettySourceURL,
|
||||
underRoot,
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @module reducers/tabs
|
||||
*/
|
||||
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import { isOriginalId } from "devtools-source-map";
|
||||
import move from "lodash-move";
|
||||
|
||||
|
@ -43,21 +43,19 @@ export type UIState = {
|
||||
conditionalPanelLocation: null | SourceLocation
|
||||
};
|
||||
|
||||
export const createUIState = makeRecord(
|
||||
({
|
||||
selectedPrimaryPaneTab: "sources",
|
||||
activeSearch: null,
|
||||
contextMenu: {},
|
||||
shownSource: null,
|
||||
startPanelCollapsed: prefs.startPanelCollapsed,
|
||||
endPanelCollapsed: prefs.endPanelCollapsed,
|
||||
frameworkGroupingOn: prefs.frameworkGroupingOn,
|
||||
highlightedLineRange: undefined,
|
||||
conditionalPanelLocation: null,
|
||||
orientation: "horizontal",
|
||||
viewport: null
|
||||
}: UIState)
|
||||
);
|
||||
export const createUIState: () => Record<UIState> = makeRecord({
|
||||
selectedPrimaryPaneTab: "sources",
|
||||
activeSearch: null,
|
||||
contextMenu: {},
|
||||
shownSource: null,
|
||||
startPanelCollapsed: prefs.startPanelCollapsed,
|
||||
endPanelCollapsed: prefs.endPanelCollapsed,
|
||||
frameworkGroupingOn: prefs.frameworkGroupingOn,
|
||||
highlightedLineRange: undefined,
|
||||
conditionalPanelLocation: null,
|
||||
orientation: "horizontal",
|
||||
viewport: null
|
||||
});
|
||||
|
||||
function update(
|
||||
state: Record<UIState> = createUIState(),
|
||||
@ -186,7 +184,7 @@ export function getConditionalPanelLocation(
|
||||
return state.ui.get("conditionalPanelLocation");
|
||||
}
|
||||
|
||||
export function getOrientation(state: OuterState): boolean {
|
||||
export function getOrientation(state: OuterState): OrientationType {
|
||||
return state.ui.get("orientation");
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import { sortBy, uniq } from "lodash";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import {
|
||||
getSources,
|
||||
getBreakpointsList,
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// @flow
|
||||
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
|
||||
import type {
|
||||
BreakpointsState,
|
||||
|
@ -13,7 +13,7 @@ import { isOriginal } from "../utils/source";
|
||||
import { get } from "lodash";
|
||||
import type { Frame, Source } from "../types";
|
||||
import type { SourcesMap } from "../reducers/sources";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
|
||||
function getLocation(frame, isGeneratedSource) {
|
||||
return isGeneratedSource
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @flow
|
||||
|
||||
import { isGeneratedId } from "devtools-source-map";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
import { getBreakpointsList } from "../reducers/breakpoints";
|
||||
@ -46,7 +46,7 @@ function isVisible(breakpoint, selectedSource) {
|
||||
|
||||
/*
|
||||
* Finds the breakpoints, which appear in the selected source.
|
||||
*/
|
||||
*/
|
||||
export const getVisibleBreakpoints = createSelector(
|
||||
getSelectedSource,
|
||||
getBreakpointsList,
|
||||
@ -63,7 +63,7 @@ export const getVisibleBreakpoints = createSelector(
|
||||
|
||||
/*
|
||||
* Finds the first breakpoint per line, which appear in the selected source.
|
||||
*/
|
||||
*/
|
||||
export const getFirstVisibleBreakpoints = createSelector(
|
||||
getVisibleBreakpoints,
|
||||
breakpoints => {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { groupBy, get, sortedUniqBy } from "lodash";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
|
||||
import { getViewport } from "../selectors";
|
||||
import { getVisibleBreakpoints } from "./visibleBreakpoints";
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import { getSelectedSource } from "../reducers/sources";
|
||||
import { getPausePoints } from "../reducers/ast";
|
||||
import { convertToList } from "../utils/pause/pausePoints";
|
||||
|
||||
export function getVisiblePausePoints(state) {
|
||||
const source = getSelectedSource(state);
|
||||
@ -12,6 +11,5 @@ export function getVisiblePausePoints(state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const pausePoints = getPausePoints(state, source.id);
|
||||
return convertToList(pausePoints);
|
||||
return getPausePoints(state, source.id);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
import { getSelectedLocation } from "../reducers/sources";
|
||||
import { getSelectedFrame } from "../reducers/pause";
|
||||
import { isOriginalId } from "devtools-source-map";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from "../utils/createSelector";
|
||||
|
||||
import type { Frame, SourceLocation } from "../types";
|
||||
|
||||
|
@ -5,18 +5,16 @@
|
||||
// @flow
|
||||
|
||||
import { xor, range } from "lodash";
|
||||
import { convertToList } from "./pause/pausePoints";
|
||||
|
||||
import type { SourceLocation, Position } from "../types";
|
||||
import type { Symbols } from "../reducers/ast";
|
||||
|
||||
import type {
|
||||
AstPosition,
|
||||
AstLocation,
|
||||
PausePoints,
|
||||
FunctionDeclaration,
|
||||
ClassDeclaration
|
||||
} from "../workers/parser";
|
||||
import type { PausePoints } from "../reducers/types";
|
||||
|
||||
export function findBestMatchExpression(symbols: Symbols, tokenPos: Position) {
|
||||
if (symbols.loading) {
|
||||
@ -43,14 +41,15 @@ export function findBestMatchExpression(symbols: Symbols, tokenPos: Position) {
|
||||
}, null);
|
||||
}
|
||||
|
||||
export function findEmptyLines(sourceText: string, pausePoints: PausePoints) {
|
||||
export function findEmptyLines(
|
||||
sourceText: string,
|
||||
pausePoints: PausePoints
|
||||
): number[] {
|
||||
if (!pausePoints || !sourceText) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const pausePointsList = convertToList(pausePoints);
|
||||
|
||||
const breakpoints = pausePointsList.filter(point => point.types.break);
|
||||
const breakpoints = pausePoints.filter(point => point.types.break);
|
||||
const breakpointLines = breakpoints.map(point => point.location.line);
|
||||
|
||||
if (!sourceText || breakpointLines.length == 0) {
|
||||
|
@ -198,12 +198,19 @@ export function sortBreakpoints(breakpoints: Breakpoint[]) {
|
||||
return _sortBreakpoints(breakpoints, "location");
|
||||
}
|
||||
|
||||
function _sortBreakpoints(breakpoints: Array<Object>, property: string) {
|
||||
return sortBy(breakpoints, [
|
||||
// Priority: line number, undefined column, column number
|
||||
`${property}.line`,
|
||||
bp => {
|
||||
return bp[property].column === undefined || bp[property].column;
|
||||
}
|
||||
]);
|
||||
function _sortBreakpoints(
|
||||
breakpoints: Array<Object>,
|
||||
property: string
|
||||
): Array<Object> {
|
||||
// prettier-ignore
|
||||
return sortBy(
|
||||
breakpoints,
|
||||
[
|
||||
// Priority: line number, undefined column, column number
|
||||
`${property}.line`,
|
||||
bp => {
|
||||
return bp[property].column === undefined || bp[property].column;
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
17
devtools/client/debugger/new/src/utils/connect.js
Normal file
17
devtools/client/debugger/new/src/utils/connect.js
Normal file
@ -0,0 +1,17 @@
|
||||
/* 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/>. */
|
||||
// @flow
|
||||
|
||||
import { connect as reduxConnect } from "react-redux";
|
||||
import * as React from "react";
|
||||
|
||||
export function connect<Config, RSP: {}, MDP: {}>(
|
||||
mapStateToProps: (state: any, props: any) => RSP,
|
||||
mapDispatchToProps?: (() => MDP) | MDP
|
||||
): (
|
||||
Component: React.AbstractComponent<Config>
|
||||
) => React.AbstractComponent<$Diff<Config, RSP & MDP>> {
|
||||
// $FlowFixMe
|
||||
return reduxConnect(mapStateToProps, mapDispatchToProps);
|
||||
}
|
12
devtools/client/debugger/new/src/utils/createSelector.js
Normal file
12
devtools/client/debugger/new/src/utils/createSelector.js
Normal file
@ -0,0 +1,12 @@
|
||||
/* 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/>. */
|
||||
|
||||
import { createSelector as reselectCreateSelector } from "reselect";
|
||||
|
||||
function createSelector(...args) {
|
||||
// $FlowFixMe
|
||||
return reselectCreateSelector(...args);
|
||||
}
|
||||
|
||||
export { createSelector };
|
@ -18,7 +18,7 @@ import { isWasm, lineToWasmOffset, wasmOffsetToLine } from "../wasm";
|
||||
|
||||
import type { AstLocation } from "../../workers/parser";
|
||||
import type { EditorPosition, EditorRange } from "../editor/types";
|
||||
import type { SourceLocation } from "../../types";
|
||||
import type { SearchModifiers, Source, SourceLocation } from "../../types";
|
||||
type Editor = Object;
|
||||
|
||||
let editor: ?Editor;
|
||||
@ -58,11 +58,11 @@ export function endOperation() {
|
||||
codeMirror.endOperation();
|
||||
}
|
||||
|
||||
export function shouldShowPrettyPrint(source) {
|
||||
export function shouldShowPrettyPrint(source: Source) {
|
||||
return shouldPrettyPrint(source);
|
||||
}
|
||||
|
||||
export function shouldShowFooter(source, horizontal) {
|
||||
export function shouldShowFooter(source: ?Source, horizontal: boolean) {
|
||||
if (!horizontal) {
|
||||
return true;
|
||||
}
|
||||
@ -72,7 +72,13 @@ export function shouldShowFooter(source, horizontal) {
|
||||
return shouldShowPrettyPrint(source) || isOriginal(source);
|
||||
}
|
||||
|
||||
export function traverseResults(e, ctx, query, dir, modifiers) {
|
||||
export function traverseResults(
|
||||
e: Event,
|
||||
ctx: any,
|
||||
query: string,
|
||||
dir: string,
|
||||
modifiers: SearchModifiers
|
||||
) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
@ -181,7 +187,7 @@ export function getLocationsInViewport({ codeMirror }: Object) {
|
||||
|
||||
export function markText(
|
||||
{ codeMirror }: Object,
|
||||
className,
|
||||
className: String,
|
||||
{ start, end }: EditorRange
|
||||
) {
|
||||
return codeMirror.markText(
|
||||
@ -191,7 +197,11 @@ export function markText(
|
||||
);
|
||||
}
|
||||
|
||||
export function lineAtHeight({ codeMirror }, sourceId, event) {
|
||||
export function lineAtHeight(
|
||||
{ codeMirror }: Object,
|
||||
sourceId: string,
|
||||
event: MouseEvent
|
||||
) {
|
||||
const _editorLine = codeMirror.lineAtHeight(event.clientY);
|
||||
return toSourceLine(sourceId, _editorLine);
|
||||
}
|
||||
@ -213,7 +223,7 @@ export function getSourceLocationFromMouseEvent(
|
||||
};
|
||||
}
|
||||
|
||||
export function forEachLine(codeMirror: Object, iter) {
|
||||
export function forEachLine(codeMirror: Object, iter: Function) {
|
||||
codeMirror.operation(() => {
|
||||
codeMirror.doc.iter(0, codeMirror.lineCount(), iter);
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user