зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1531350 - [release 128] [Breakpoints] use the selected location for column breakpoints.
Differential Revision: https://phabricator.services.mozilla.com/D21843 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
3688c50ea4
Коммит
f81988d9c0
|
@ -35,6 +35,17 @@ const { clearWasmXScopes } = require("./utils/wasmXScopes");
|
|||
|
||||
import type { SourceLocation, Source, SourceId } from "debugger-html";
|
||||
|
||||
type Range = {
|
||||
start: {
|
||||
line: number,
|
||||
column: number
|
||||
},
|
||||
end: {
|
||||
line: number,
|
||||
column: number
|
||||
}
|
||||
};
|
||||
|
||||
async function getOriginalURLs(
|
||||
generatedSource: Source
|
||||
): Promise<SourceMapConsumer> {
|
||||
|
@ -343,21 +354,12 @@ async function getGeneratedRangesForOriginal(
|
|||
sourceId: SourceId,
|
||||
url: string,
|
||||
mergeUnmappedRegions: boolean = false
|
||||
): Promise<
|
||||
Array<{
|
||||
start: {
|
||||
line: number,
|
||||
column: number
|
||||
},
|
||||
end: {
|
||||
line: number,
|
||||
column: number
|
||||
}
|
||||
}>
|
||||
> {
|
||||
): Promise<Range[]> {
|
||||
assert(isOriginalId(sourceId), "Source is not an original source");
|
||||
|
||||
const map = await getSourceMap(originalToGeneratedId(sourceId));
|
||||
|
||||
// NOTE: this is only needed for Flow
|
||||
if (!map) {
|
||||
return [];
|
||||
}
|
||||
|
@ -367,9 +369,18 @@ async function getGeneratedRangesForOriginal(
|
|||
map.computeColumnSpans();
|
||||
}
|
||||
|
||||
const cachedGeneratedMappingsForOriginal = GENERATED_MAPPINGS.get(map);
|
||||
if (cachedGeneratedMappingsForOriginal) {
|
||||
return cachedGeneratedMappingsForOriginal;
|
||||
if (!GENERATED_MAPPINGS.has(map)) {
|
||||
GENERATED_MAPPINGS.set(map, new Map());
|
||||
}
|
||||
|
||||
const generatedRangesMap = GENERATED_MAPPINGS.get(map);
|
||||
if (!generatedRangesMap) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (generatedRangesMap.has(sourceId)) {
|
||||
// NOTE we need to coerce the result to an array for Flow
|
||||
return generatedRangesMap.get(sourceId) || [];
|
||||
}
|
||||
|
||||
// Gather groups of mappings on the generated file, with new groups created
|
||||
|
@ -445,7 +456,7 @@ async function getGeneratedRangesForOriginal(
|
|||
}
|
||||
}
|
||||
|
||||
GENERATED_MAPPINGS.set(map, generatedMappingsForOriginal);
|
||||
generatedRangesMap.set(sourceId, generatedMappingsForOriginal);
|
||||
return generatedMappingsForOriginal;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,10 @@ export function setOutOfScopeLocations() {
|
|||
|
||||
const source = getSourceFromId(getState(), location.sourceId);
|
||||
|
||||
if (!isLoaded(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let locations = null;
|
||||
if (location.line && source && !source.isWasm && isPaused(getState())) {
|
||||
locations = await parser.findOutOfScopeLocations(
|
||||
|
|
|
@ -9,21 +9,20 @@ import {
|
|||
assertBreakpoint,
|
||||
createBreakpoint,
|
||||
getASTLocation,
|
||||
assertLocation,
|
||||
makeBreakpointId,
|
||||
makeBreakpointLocation
|
||||
makeBreakpointLocation,
|
||||
findPosition
|
||||
} from "../../utils/breakpoint";
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import {
|
||||
getSource,
|
||||
getSymbols,
|
||||
getFirstVisibleBreakpointPosition
|
||||
getFirstVisibleBreakpointPosition,
|
||||
getBreakpointPositionsForSource,
|
||||
getSourceFromId
|
||||
} from "../../selectors";
|
||||
import { getGeneratedLocation } from "../../utils/source-maps";
|
||||
|
||||
import { getTextAtPosition } from "../../utils/source";
|
||||
import { recordEvent } from "../../utils/telemetry";
|
||||
import { features } from "../../utils/prefs";
|
||||
import { setBreakpointPositions } from "./breakpointPositions";
|
||||
|
||||
import type {
|
||||
BreakpointOptions,
|
||||
|
@ -34,35 +33,9 @@ import type { ThunkArgs } from "../types";
|
|||
|
||||
async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
|
||||
const state = getState();
|
||||
const source = getSource(state, breakpoint.location.sourceId);
|
||||
|
||||
if (!source) {
|
||||
throw new Error(`Unable to find source: ${breakpoint.location.sourceId}`);
|
||||
}
|
||||
|
||||
const location = {
|
||||
...breakpoint.location,
|
||||
sourceId: source.id,
|
||||
sourceUrl: source.url
|
||||
};
|
||||
|
||||
const generatedLocation = await getGeneratedLocation(
|
||||
state,
|
||||
source,
|
||||
location,
|
||||
sourceMaps
|
||||
);
|
||||
|
||||
const generatedSource = getSource(state, generatedLocation.sourceId);
|
||||
|
||||
if (!generatedSource) {
|
||||
throw new Error(
|
||||
`Unable to find generated source: ${generatedLocation.sourceId}`
|
||||
);
|
||||
}
|
||||
|
||||
assertLocation(location);
|
||||
assertLocation(generatedLocation);
|
||||
const { location, generatedLocation } = breakpoint;
|
||||
const source = getSourceFromId(state, location.sourceId);
|
||||
const generatedSource = getSourceFromId(state, generatedLocation.sourceId);
|
||||
|
||||
if (breakpointExists(state, location)) {
|
||||
const newBreakpoint = { ...breakpoint, location, generatedLocation };
|
||||
|
@ -128,20 +101,21 @@ export function addBreakpoint(
|
|||
) {
|
||||
return async ({ dispatch, getState, sourceMaps, client }: ThunkArgs) => {
|
||||
recordEvent("add_breakpoint");
|
||||
let breakpointPosition = location;
|
||||
if (features.columnBreakpoints && location.column === undefined) {
|
||||
await dispatch(setBreakpointPositions(location.sourceId));
|
||||
breakpointPosition = getFirstVisibleBreakpointPosition(
|
||||
getState(),
|
||||
location
|
||||
);
|
||||
let position;
|
||||
const { sourceId, column } = location;
|
||||
|
||||
if (column === undefined) {
|
||||
position = getFirstVisibleBreakpointPosition(getState(), location);
|
||||
} else {
|
||||
const positions = getBreakpointPositionsForSource(getState(), sourceId);
|
||||
position = findPosition(positions, location);
|
||||
}
|
||||
|
||||
if (!breakpointPosition) {
|
||||
if (!position) {
|
||||
return;
|
||||
}
|
||||
|
||||
const breakpoint = createBreakpoint(breakpointPosition, { options });
|
||||
const breakpoint = createBreakpoint(position, { options });
|
||||
|
||||
return dispatch({
|
||||
type: "ADD_BREAKPOINT",
|
||||
|
|
|
@ -5,55 +5,74 @@
|
|||
// @flow
|
||||
|
||||
import { isOriginalId, originalToGeneratedId } from "devtools-source-map";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
import { getSourceFromId, hasBreakpointPositions } from "../../selectors";
|
||||
import {
|
||||
getSource,
|
||||
getSourceFromId,
|
||||
hasBreakpointPositions,
|
||||
getBreakpointPositionsForSource
|
||||
} from "../../selectors";
|
||||
|
||||
import type { MappedLocation, SourceLocation } from "../../types";
|
||||
import type { ThunkArgs } from "../../actions/types";
|
||||
import { getOriginalLocation } from "../../utils/source-maps";
|
||||
import { makeBreakpointId } from "../../utils/breakpoint";
|
||||
import typeof SourceMaps from "../../../packages/devtools-source-map/src";
|
||||
|
||||
const requests = new Map();
|
||||
|
||||
async function mapLocations(generatedLocations, state, source, sourceMaps) {
|
||||
async function mapLocations(
|
||||
generatedLocations: SourceLocation[],
|
||||
{ sourceMaps }: { sourceMaps: SourceMaps }
|
||||
) {
|
||||
return Promise.all(
|
||||
generatedLocations.map(async generatedLocation => {
|
||||
const location = await getOriginalLocation(
|
||||
generatedLocation,
|
||||
source,
|
||||
sourceMaps
|
||||
);
|
||||
(generatedLocations: any).map(async (generatedLocation: SourceLocation) => {
|
||||
const location = await getOriginalLocation(generatedLocation, sourceMaps);
|
||||
|
||||
return { location, generatedLocation };
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function convertToList(results, sourceId) {
|
||||
function filterByUniqLocation(positions: MappedLocation[]) {
|
||||
return uniqBy(positions, ({ location }) => makeBreakpointId(location));
|
||||
}
|
||||
|
||||
function convertToList(results, source) {
|
||||
const { id, url } = source;
|
||||
const positions = [];
|
||||
|
||||
for (const line in results) {
|
||||
for (const column of results[line]) {
|
||||
positions.push({ line: Number(line), column: column, sourceId });
|
||||
positions.push({
|
||||
line: Number(line),
|
||||
column: column,
|
||||
sourceId: id,
|
||||
sourceUrl: url
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
async function getBreakpointPositions(
|
||||
sourceId,
|
||||
{ client, dispatch, getState, sourceMaps }
|
||||
) {
|
||||
let source = getSourceFromId(getState(), sourceId);
|
||||
async function _setBreakpointPositions(sourceId, thunkArgs) {
|
||||
const { client, dispatch, getState, sourceMaps } = thunkArgs;
|
||||
let generatedSource = getSource(getState(), sourceId);
|
||||
if (!generatedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
let results = {};
|
||||
if (isOriginalId(sourceId)) {
|
||||
const ranges = await sourceMaps.getGeneratedRangesForOriginal(
|
||||
sourceId,
|
||||
source.url,
|
||||
generatedSource.url,
|
||||
true
|
||||
);
|
||||
sourceId = originalToGeneratedId(sourceId);
|
||||
source = getSourceFromId(getState(), sourceId);
|
||||
const generatedSourceId = originalToGeneratedId(sourceId);
|
||||
generatedSource = getSourceFromId(getState(), generatedSourceId);
|
||||
|
||||
// Note: While looping here may not look ideal, in the vast majority of
|
||||
// cases, the number of ranges here should be very small, and is quite
|
||||
|
@ -67,25 +86,26 @@ async function getBreakpointPositions(
|
|||
range.end.column = 0;
|
||||
}
|
||||
|
||||
const bps = await client.getBreakpointPositions(source.actors[0], range);
|
||||
const bps = await client.getBreakpointPositions(generatedSource, range);
|
||||
for (const line in bps) {
|
||||
results[line] = (results[line] || []).concat(bps[line]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results = await client.getBreakpointPositions(source.actors[0]);
|
||||
results = await client.getBreakpointPositions(generatedSource);
|
||||
}
|
||||
|
||||
const positions = convertToList(results, sourceId);
|
||||
return mapLocations(positions, getState(), source, sourceMaps);
|
||||
let positions = convertToList(results, generatedSource);
|
||||
positions = await mapLocations(positions, thunkArgs);
|
||||
positions = filterByUniqLocation(positions);
|
||||
dispatch({ type: "ADD_BREAKPOINT_POSITIONS", sourceId, positions });
|
||||
}
|
||||
|
||||
export function setBreakpointPositions(sourceId: string) {
|
||||
return async (thunkArgs: ThunkArgs) => {
|
||||
const { dispatch, getState } = thunkArgs;
|
||||
|
||||
const { getState } = thunkArgs;
|
||||
if (hasBreakpointPositions(getState(), sourceId)) {
|
||||
return;
|
||||
return getBreakpointPositionsForSource(getState(), sourceId);
|
||||
}
|
||||
|
||||
if (!requests.has(sourceId)) {
|
||||
|
@ -93,11 +113,7 @@ export function setBreakpointPositions(sourceId: string) {
|
|||
sourceId,
|
||||
(async () => {
|
||||
try {
|
||||
dispatch({
|
||||
type: "ADD_BREAKPOINT_POSITIONS",
|
||||
sourceId,
|
||||
positions: await getBreakpointPositions(sourceId, thunkArgs)
|
||||
});
|
||||
await _setBreakpointPositions(sourceId, thunkArgs);
|
||||
} finally {
|
||||
requests.delete(sourceId);
|
||||
}
|
||||
|
@ -106,5 +122,6 @@ export function setBreakpointPositions(sourceId: string) {
|
|||
}
|
||||
|
||||
await requests.get(sourceId);
|
||||
return getBreakpointPositionsForSource(getState(), sourceId);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,19 +6,19 @@
|
|||
|
||||
import { setBreakpointPositions } from "./breakpointPositions";
|
||||
import {
|
||||
locationMoved,
|
||||
createBreakpoint,
|
||||
assertBreakpoint,
|
||||
assertPendingBreakpoint,
|
||||
findScopeByName,
|
||||
findFunctionByName,
|
||||
findPosition,
|
||||
makeBreakpointLocation
|
||||
} from "../../utils/breakpoint";
|
||||
|
||||
import { getGeneratedLocation } from "../../utils/source-maps";
|
||||
import { getTextAtPosition } from "../../utils/source";
|
||||
import { comparePosition } from "../../utils/location";
|
||||
|
||||
import { originalToGeneratedId, isOriginalId } from "devtools-source-map";
|
||||
import { getSource, getBreakpointPositionsForSource } from "../../selectors";
|
||||
import { features } from "../../utils/prefs";
|
||||
import { getSource } from "../../selectors";
|
||||
|
||||
import type { ThunkArgs, Action } from "../types";
|
||||
|
||||
|
@ -35,29 +35,28 @@ type BreakpointSyncData = {
|
|||
breakpoint: ?Breakpoint
|
||||
};
|
||||
|
||||
async function isPossiblePosition(state, location, dispatch) {
|
||||
if (!features.columnBreakpoints || location.column != undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
await dispatch(setBreakpointPositions(location.sourceId));
|
||||
const positions = getBreakpointPositionsForSource(state, location.sourceId);
|
||||
return (
|
||||
positions &&
|
||||
positions.some(({ generatedLocation }) => generatedLocation.column)
|
||||
);
|
||||
async function findBreakpointPosition(
|
||||
{ getState, dispatch },
|
||||
location: SourceLocation
|
||||
) {
|
||||
const positions = await dispatch(setBreakpointPositions(location.sourceId));
|
||||
const position = findPosition(positions, location);
|
||||
return position && position.generatedLocation;
|
||||
}
|
||||
|
||||
async function makeScopedLocation(
|
||||
async function findNewLocation(
|
||||
{ name, offset, index }: ASTLocation,
|
||||
location: SourceLocation,
|
||||
source
|
||||
) {
|
||||
const scope = await findScopeByName(source, name, index);
|
||||
// fallback onto the location line, if the scope is not found
|
||||
// note: we may at some point want to delete the breakpoint if the scope
|
||||
// disappears
|
||||
const line = scope ? scope.location.start.line + offset.line : location.line;
|
||||
const func = await findFunctionByName(source, name, index);
|
||||
|
||||
// Fallback onto the location line, if we do not find a function is not found
|
||||
let line = location.line;
|
||||
if (func) {
|
||||
line = func.location.start.line + offset.line;
|
||||
}
|
||||
|
||||
return {
|
||||
line,
|
||||
column: location.column,
|
||||
|
@ -76,11 +75,13 @@ function createSyncData(
|
|||
): BreakpointSyncData {
|
||||
const overrides = {
|
||||
...pendingBreakpoint,
|
||||
generatedLocation,
|
||||
text,
|
||||
originalText
|
||||
};
|
||||
const breakpoint = createBreakpoint(location, overrides);
|
||||
const breakpoint = createBreakpoint(
|
||||
{ generatedLocation, location },
|
||||
overrides
|
||||
);
|
||||
|
||||
assertBreakpoint(breakpoint);
|
||||
return { breakpoint, previousLocation };
|
||||
|
@ -89,13 +90,11 @@ function createSyncData(
|
|||
// we have three forms of syncing: disabled syncing, existing server syncing
|
||||
// and adding a new breakpoint
|
||||
export async function syncBreakpointPromise(
|
||||
getState: Function,
|
||||
client: Object,
|
||||
sourceMaps: Object,
|
||||
dispatch: Function,
|
||||
thunkArgs: ThunkArgs,
|
||||
sourceId: SourceId,
|
||||
pendingBreakpoint: PendingBreakpoint
|
||||
): Promise<BreakpointSyncData | null> {
|
||||
): Promise<BreakpointSyncData> {
|
||||
const { getState, client } = thunkArgs;
|
||||
assertPendingBreakpoint(pendingBreakpoint);
|
||||
|
||||
const source = getSource(getState(), sourceId);
|
||||
|
@ -106,70 +105,47 @@ export async function syncBreakpointPromise(
|
|||
|
||||
const generatedSource = getSource(getState(), generatedSourceId);
|
||||
|
||||
if (!source) {
|
||||
return null;
|
||||
if (!source || !generatedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { location, astLocation } = pendingBreakpoint;
|
||||
const { location, generatedLocation, astLocation } = pendingBreakpoint;
|
||||
const previousLocation = { ...location, sourceId };
|
||||
|
||||
const scopedLocation = await makeScopedLocation(
|
||||
const newLocation = await findNewLocation(
|
||||
astLocation,
|
||||
previousLocation,
|
||||
source
|
||||
);
|
||||
|
||||
const scopedGeneratedLocation = await getGeneratedLocation(
|
||||
getState(),
|
||||
source,
|
||||
scopedLocation,
|
||||
sourceMaps
|
||||
const newGeneratedLocation = await findBreakpointPosition(
|
||||
thunkArgs,
|
||||
newLocation
|
||||
);
|
||||
|
||||
// this is the generatedLocation of the pending breakpoint, with
|
||||
// the source id updated to reflect the new connection
|
||||
const generatedLocation = {
|
||||
...pendingBreakpoint.generatedLocation,
|
||||
sourceId: generatedSourceId
|
||||
};
|
||||
|
||||
const isSameLocation = !locationMoved(
|
||||
const isSameLocation = comparePosition(
|
||||
generatedLocation,
|
||||
scopedGeneratedLocation
|
||||
);
|
||||
|
||||
// makeBreakpointLocation requires the source to still exist, which might not
|
||||
// be the case if we navigated.
|
||||
if (!getSource(getState(), generatedSourceId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const breakpointLocation = makeBreakpointLocation(
|
||||
getState(),
|
||||
generatedLocation
|
||||
);
|
||||
|
||||
const possiblePosition = await isPossiblePosition(
|
||||
getState(),
|
||||
generatedLocation,
|
||||
dispatch
|
||||
newGeneratedLocation
|
||||
);
|
||||
|
||||
/** ******* CASE 1: No server change ***********/
|
||||
// early return if breakpoint is disabled or we are in the sameLocation
|
||||
if (possiblePosition && (pendingBreakpoint.disabled || isSameLocation)) {
|
||||
if (newGeneratedLocation && (pendingBreakpoint.disabled || isSameLocation)) {
|
||||
// Make sure the breakpoint is installed on all source actors.
|
||||
if (!pendingBreakpoint.disabled) {
|
||||
await client.setBreakpoint(breakpointLocation, pendingBreakpoint.options);
|
||||
await client.setBreakpoint(
|
||||
makeBreakpointLocation(getState(), newGeneratedLocation),
|
||||
pendingBreakpoint.options
|
||||
);
|
||||
}
|
||||
|
||||
const originalText = getTextAtPosition(source, previousLocation);
|
||||
const text = getTextAtPosition(generatedSource, generatedLocation);
|
||||
const text = getTextAtPosition(generatedSource, newGeneratedLocation);
|
||||
|
||||
return createSyncData(
|
||||
pendingBreakpoint,
|
||||
scopedLocation,
|
||||
scopedGeneratedLocation,
|
||||
newLocation,
|
||||
newGeneratedLocation,
|
||||
previousLocation,
|
||||
text,
|
||||
originalText
|
||||
|
@ -177,9 +153,9 @@ export async function syncBreakpointPromise(
|
|||
}
|
||||
|
||||
// clear server breakpoints if they exist and we have moved
|
||||
await client.removeBreakpoint(breakpointLocation);
|
||||
await client.removeBreakpoint(generatedLocation);
|
||||
|
||||
if (!possiblePosition || !scopedGeneratedLocation.line) {
|
||||
if (!newGeneratedLocation) {
|
||||
return { previousLocation, breakpoint: null };
|
||||
}
|
||||
|
||||
|
@ -187,17 +163,17 @@ export async function syncBreakpointPromise(
|
|||
// If we are not disabled, set the breakpoint on the server and get
|
||||
// that info so we can set it on our breakpoints.
|
||||
await client.setBreakpoint(
|
||||
scopedGeneratedLocation,
|
||||
makeBreakpointLocation(getState(), newGeneratedLocation),
|
||||
pendingBreakpoint.options
|
||||
);
|
||||
|
||||
const originalText = getTextAtPosition(source, scopedLocation);
|
||||
const text = getTextAtPosition(generatedSource, scopedGeneratedLocation);
|
||||
const originalText = getTextAtPosition(source, newLocation);
|
||||
const text = getTextAtPosition(generatedSource, newGeneratedLocation);
|
||||
|
||||
return createSyncData(
|
||||
pendingBreakpoint,
|
||||
scopedLocation,
|
||||
scopedGeneratedLocation,
|
||||
newLocation,
|
||||
newGeneratedLocation,
|
||||
previousLocation,
|
||||
text,
|
||||
originalText
|
||||
|
@ -207,22 +183,16 @@ export async function syncBreakpointPromise(
|
|||
/**
|
||||
* Syncing a breakpoint add breakpoint information that is stored, and
|
||||
* contact the server for more data.
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {String} $1.sourceId String value
|
||||
* @param {PendingBreakpoint} $1.location PendingBreakpoint value
|
||||
*/
|
||||
export function syncBreakpoint(
|
||||
sourceId: SourceId,
|
||||
pendingBreakpoint: PendingBreakpoint
|
||||
) {
|
||||
return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
|
||||
return async (thunkArgs: ThunkArgs) => {
|
||||
const { dispatch } = thunkArgs;
|
||||
|
||||
const response = await syncBreakpointPromise(
|
||||
getState,
|
||||
client,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
thunkArgs,
|
||||
sourceId,
|
||||
pendingBreakpoint
|
||||
);
|
||||
|
@ -232,7 +202,6 @@ export function syncBreakpoint(
|
|||
}
|
||||
|
||||
const { breakpoint, previousLocation } = response;
|
||||
|
||||
return dispatch(
|
||||
({
|
||||
type: "SYNC_BREAKPOINT",
|
||||
|
|
|
@ -9,6 +9,7 @@ Array [
|
|||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 1,
|
||||
"line": 2,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
@ -16,13 +17,15 @@ Array [
|
|||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": 1,
|
||||
"line": 2,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
},
|
||||
"id": "a:2:",
|
||||
"id": "a:2:1",
|
||||
"loading": false,
|
||||
"location": Object {
|
||||
"column": 1,
|
||||
"line": 2,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
@ -64,6 +67,7 @@ Object {
|
|||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 1,
|
||||
"sourceId": "a.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/a.js",
|
||||
|
@ -71,6 +75,7 @@ Object {
|
|||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": 0,
|
||||
"line": 1,
|
||||
"sourceId": "a.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/a.js",
|
||||
|
@ -102,6 +107,7 @@ Array [
|
|||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 1,
|
||||
"line": 5,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
@ -109,13 +115,15 @@ Array [
|
|||
},
|
||||
"disabled": true,
|
||||
"generatedLocation": Object {
|
||||
"column": 1,
|
||||
"line": 5,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
},
|
||||
"id": "a:5:",
|
||||
"id": "a:5:1",
|
||||
"loading": false,
|
||||
"location": Object {
|
||||
"column": 1,
|
||||
"line": 5,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
|
|
@ -31,8 +31,18 @@ describe("breakpointPositions", () => {
|
|||
selectors.getBreakpointPositionsForSource(getState(), "foo")
|
||||
).toEqual([
|
||||
{
|
||||
location: { line: 9, column: 1, sourceId: "foo" },
|
||||
generatedLocation: { line: 9, column: 1, sourceId: "foo" }
|
||||
location: {
|
||||
line: 9,
|
||||
column: 1,
|
||||
sourceId: "foo",
|
||||
sourceUrl: "http://localhost:8000/examples/foo"
|
||||
},
|
||||
generatedLocation: {
|
||||
line: 9,
|
||||
column: 1,
|
||||
sourceId: "foo",
|
||||
sourceUrl: "http://localhost:8000/examples/foo"
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
@ -63,8 +73,18 @@ describe("breakpointPositions", () => {
|
|||
selectors.getBreakpointPositionsForSource(getState(), "foo")
|
||||
).toEqual([
|
||||
{
|
||||
location: { line: 9, column: 1, sourceId: "foo" },
|
||||
generatedLocation: { line: 9, column: 1, sourceId: "foo" }
|
||||
location: {
|
||||
line: 9,
|
||||
column: 1,
|
||||
sourceId: "foo",
|
||||
sourceUrl: "http://localhost:8000/examples/foo"
|
||||
},
|
||||
generatedLocation: {
|
||||
line: 9,
|
||||
column: 1,
|
||||
sourceId: "foo",
|
||||
sourceUrl: "http://localhost:8000/examples/foo"
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
|
|
|
@ -14,18 +14,34 @@ import {
|
|||
|
||||
import { simpleMockThreadClient } from "../../tests/helpers/threadClient.js";
|
||||
|
||||
function mockClient(positionsResponse = {}) {
|
||||
return {
|
||||
...simpleMockThreadClient,
|
||||
getBreakpointPositions: async () => positionsResponse
|
||||
};
|
||||
}
|
||||
|
||||
describe("breakpoints", () => {
|
||||
it("should add a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "2": [1] }));
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 2,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
const source = makeSource("a");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
await dispatch(
|
||||
actions.setSelectedLocation(source, {
|
||||
line: 1,
|
||||
column: 1,
|
||||
sourceId: source.id
|
||||
})
|
||||
);
|
||||
|
||||
await dispatch(actions.addBreakpoint(loc1));
|
||||
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
|
@ -38,15 +54,24 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should not show a breakpoint that does not have text", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
const source = makeSource("a");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
await dispatch(
|
||||
actions.setSelectedLocation(source, {
|
||||
line: 1,
|
||||
column: 1,
|
||||
sourceId: source.id
|
||||
})
|
||||
);
|
||||
|
||||
await dispatch(actions.addBreakpoint(loc1));
|
||||
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
|
@ -56,15 +81,24 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should show a disabled breakpoint that does not have text", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
const source = makeSource("a");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
await dispatch(
|
||||
actions.setSelectedLocation(source, {
|
||||
line: 1,
|
||||
column: 1,
|
||||
sourceId: source.id
|
||||
})
|
||||
);
|
||||
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc1));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
|
@ -75,16 +109,24 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should not re-add a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
const source = makeSource("a");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
await dispatch(
|
||||
actions.setSelectedLocation(source, {
|
||||
line: 1,
|
||||
column: 1,
|
||||
sourceId: source.id
|
||||
})
|
||||
);
|
||||
|
||||
await dispatch(actions.addBreakpoint(loc1));
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
|
@ -96,17 +138,21 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should remove a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(
|
||||
mockClient({ "5": [1], "6": [2] })
|
||||
);
|
||||
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
const loc2 = {
|
||||
sourceId: "b",
|
||||
line: 6,
|
||||
column: 2,
|
||||
sourceUrl: "http://localhost:8000/examples/b"
|
||||
};
|
||||
|
||||
|
@ -118,6 +164,14 @@ describe("breakpoints", () => {
|
|||
await dispatch(actions.newSource(bSource));
|
||||
await dispatch(actions.loadSourceText(bSource));
|
||||
|
||||
await dispatch(
|
||||
actions.setSelectedLocation(aSource, {
|
||||
line: 1,
|
||||
column: 1,
|
||||
sourceId: aSource.id
|
||||
})
|
||||
);
|
||||
|
||||
await dispatch(actions.addBreakpoint(loc1));
|
||||
await dispatch(actions.addBreakpoint(loc2));
|
||||
|
||||
|
@ -131,17 +185,21 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should disable a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(
|
||||
mockClient({ "5": [1], "6": [2] })
|
||||
);
|
||||
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
const loc2 = {
|
||||
sourceId: "b",
|
||||
line: 6,
|
||||
column: 2,
|
||||
sourceUrl: "http://localhost:8000/examples/b"
|
||||
};
|
||||
|
||||
|
@ -163,10 +221,13 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should enable breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(
|
||||
mockClient({ "5": [1], "6": [2] })
|
||||
);
|
||||
const loc = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
|
@ -187,17 +248,21 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should toggle all the breakpoints", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(
|
||||
mockClient({ "5": [1], "6": [2] })
|
||||
);
|
||||
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
const loc2 = {
|
||||
sourceId: "b",
|
||||
line: 6,
|
||||
column: 2,
|
||||
sourceUrl: "http://localhost:8000/examples/b"
|
||||
};
|
||||
|
||||
|
@ -216,6 +281,7 @@ describe("breakpoints", () => {
|
|||
|
||||
let bp1 = selectors.getBreakpoint(getState(), loc1);
|
||||
let bp2 = selectors.getBreakpoint(getState(), loc2);
|
||||
|
||||
expect(bp1 && bp1.disabled).toBe(true);
|
||||
expect(bp2 && bp2.disabled).toBe(true);
|
||||
|
||||
|
@ -228,16 +294,16 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should toggle a breakpoint at a location", async () => {
|
||||
const location = { sourceId: "foo1", line: 5 };
|
||||
const getBp = () => selectors.getBreakpoint(getState(), location);
|
||||
const loc = { sourceId: "foo1", line: 5, column: 1 };
|
||||
const getBp = () => selectors.getBreakpoint(getState(), loc);
|
||||
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
|
||||
const source = makeSource("foo1");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
|
||||
await dispatch(actions.selectLocation({ sourceId: "foo1", line: 1 }));
|
||||
await dispatch(actions.selectLocation(loc));
|
||||
|
||||
await dispatch(actions.toggleBreakpointAtLine(5));
|
||||
const bp = getBp();
|
||||
|
@ -248,10 +314,10 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should disable/enable a breakpoint at a location", async () => {
|
||||
const location = { sourceId: "foo1", line: 5 };
|
||||
const location = { sourceId: "foo1", line: 5, column: 1 };
|
||||
const getBp = () => selectors.getBreakpoint(getState(), location);
|
||||
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
|
||||
const source = makeSource("foo1");
|
||||
await dispatch(actions.newSource(source));
|
||||
|
@ -272,11 +338,12 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should set the breakpoint condition", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
|
||||
const loc = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
|
@ -301,15 +368,19 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should set the condition and enable a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "5": [1] }));
|
||||
|
||||
const loc = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
column: 1,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
|
||||
await dispatch(actions.newSource(makeSource("a")));
|
||||
const source = makeSource("a");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
|
@ -330,11 +401,12 @@ describe("breakpoints", () => {
|
|||
});
|
||||
|
||||
it("should remap breakpoints on pretty print", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
const { dispatch, getState } = createStore(mockClient({ "1": [0] }));
|
||||
|
||||
const loc = {
|
||||
sourceId: "a.js",
|
||||
line: 1,
|
||||
column: 0,
|
||||
sourceUrl: "http://localhost:8000/examples/a.js"
|
||||
};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ const mockThreadClient = {
|
|||
evaluate: async () => {},
|
||||
evaluateInFrame: async () => {},
|
||||
evaluateExpressions: async () => {},
|
||||
|
||||
resume: async () => {},
|
||||
getFrameScopes: async frame => frame.scope,
|
||||
setBreakpoint: () => new Promise(_resolve => {}),
|
||||
sourceContents: ({ source }) => {
|
||||
|
@ -69,7 +69,8 @@ const mockThreadClient = {
|
|||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getBreakpointPositions: async () => ({})
|
||||
};
|
||||
|
||||
const mockFrameId = "1";
|
||||
|
@ -320,7 +321,8 @@ describe("pause", () => {
|
|||
getOriginalSourceText: async () => ({
|
||||
source: "fn fooBar() {}\nfn barZoo() { fooBar() }",
|
||||
contentType: "text/rust"
|
||||
})
|
||||
}),
|
||||
getGeneratedRangesForOriginal: async () => []
|
||||
};
|
||||
|
||||
const store = createStore(mockThreadClient, {}, sourceMapsMock);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { getGeneratedSource, getSource } from "../../selectors";
|
||||
import { setBreakpointPositions } from "../breakpoints";
|
||||
|
||||
import * as parser from "../../workers/parser";
|
||||
import { isLoaded, isOriginal } from "../../utils/source";
|
||||
import { Telemetry } from "devtools-modules";
|
||||
|
@ -86,8 +88,9 @@ export function loadSourceText(source: ?Source) {
|
|||
await dispatch(loadSourceText(generatedSource));
|
||||
}
|
||||
|
||||
if (!newSource.isWasm) {
|
||||
if (!newSource.isWasm && isLoaded(newSource)) {
|
||||
await parser.setSource(newSource);
|
||||
await dispatch(setBreakpointPositions(newSource.id));
|
||||
}
|
||||
|
||||
// signal that the action is finished
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import assert from "../../utils/assert";
|
||||
import { recordEvent } from "../../utils/telemetry";
|
||||
import { remapBreakpoints } from "../breakpoints";
|
||||
import { remapBreakpoints, setBreakpointPositions } from "../breakpoints";
|
||||
|
||||
import { setSymbols } from "../ast";
|
||||
import { prettyPrint } from "../../workers/pretty-print";
|
||||
|
@ -66,8 +66,8 @@ export function createPrettySource(sourceId: string) {
|
|||
};
|
||||
|
||||
setSource(loadedPrettySource);
|
||||
|
||||
dispatch(({ type: "UPDATE_SOURCE", source: loadedPrettySource }: Action));
|
||||
await dispatch(setBreakpointPositions(loadedPrettySource.id));
|
||||
|
||||
return prettySource;
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ import { loadSourceText } from "./loadSourceText";
|
|||
import { prefs } from "../../utils/prefs";
|
||||
import { shouldPrettyPrint, isMinified } from "../../utils/source";
|
||||
import { createLocation } from "../../utils/location";
|
||||
import { getMappedLocation } from "../../utils/source-maps";
|
||||
import { mapLocation } from "../../utils/source-maps";
|
||||
|
||||
import {
|
||||
getSource,
|
||||
|
@ -133,7 +133,7 @@ export function selectLocation(
|
|||
selectedSource &&
|
||||
isOriginalId(selectedSource.id) != isOriginalId(location.sourceId)
|
||||
) {
|
||||
location = await getMappedLocation(getState(), sourceMaps, location);
|
||||
location = await mapLocation(getState(), sourceMaps, location);
|
||||
source = getSourceFromId(getState(), location.sourceId);
|
||||
}
|
||||
|
||||
|
@ -192,11 +192,7 @@ export function jumpToMappedLocation(location: SourceLocation) {
|
|||
return;
|
||||
}
|
||||
|
||||
const pairedLocation = await getMappedLocation(
|
||||
getState(),
|
||||
sourceMaps,
|
||||
location
|
||||
);
|
||||
const pairedLocation = await mapLocation(getState(), sourceMaps, location);
|
||||
|
||||
return dispatch(selectSpecificLocation({ ...pairedLocation }));
|
||||
};
|
||||
|
|
|
@ -46,7 +46,8 @@ describe("loadSourceText", () => {
|
|||
new Promise(r => {
|
||||
count++;
|
||||
resolve = r;
|
||||
})
|
||||
}),
|
||||
getBreakpointPositions: async () => ({})
|
||||
});
|
||||
const id = "foo";
|
||||
const baseSource = makeSource(id, { loadedState: "unloaded" });
|
||||
|
@ -78,7 +79,8 @@ describe("loadSourceText", () => {
|
|||
new Promise(r => {
|
||||
count++;
|
||||
resolve = r;
|
||||
})
|
||||
}),
|
||||
getBreakpointPositions: async () => ({})
|
||||
});
|
||||
const id = "foo";
|
||||
const baseSource = makeSource(id, { loadedState: "unloaded" });
|
||||
|
|
|
@ -230,7 +230,8 @@ describe("sources", () => {
|
|||
{
|
||||
getOriginalLocation: async location => ({ ...location, line: 12 }),
|
||||
getGeneratedLocation: async location => ({ ...location, line: 12 }),
|
||||
getOriginalSourceText: async () => ({ source: "" })
|
||||
getOriginalSourceText: async () => ({ source: "" }),
|
||||
getGeneratedRangesForOriginal: async () => []
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -254,10 +255,16 @@ describe("sources", () => {
|
|||
const { dispatch, getState } = createStore(
|
||||
sourceThreadClient,
|
||||
{},
|
||||
{ getOriginalLocation: async location => ({ ...location, line: 12 }) }
|
||||
{
|
||||
getOriginalLocation: async location => ({ ...location, line: 12 }),
|
||||
getGeneratedRangesForOriginal: async () => [],
|
||||
getOriginalSourceText: async () => ({ source: "" })
|
||||
}
|
||||
);
|
||||
|
||||
await dispatch(actions.newSource(makeSource("base.js")));
|
||||
const baseSource = makeOriginalSource("base.js");
|
||||
|
||||
await dispatch(actions.newSource(baseSource));
|
||||
await dispatch(actions.selectSource(baseSource.id));
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`initializing when pending breakpoints exist in prefs syncs pending breakpoints 1`] = `
|
||||
Object {
|
||||
"http://localhost:8000/examples/bar.js:5:": Object {
|
||||
"http://localhost:8000/examples/bar.js:5:1": Object {
|
||||
"astLocation": Object {
|
||||
"index": 0,
|
||||
"name": undefined,
|
||||
|
@ -12,12 +12,12 @@ Object {
|
|||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"column": 1,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/bar.js",
|
||||
},
|
||||
"location": Object {
|
||||
"column": undefined,
|
||||
"column": 1,
|
||||
"line": 5,
|
||||
"sourceId": "",
|
||||
"sourceUrl": "http://localhost:8000/examples/bar.js",
|
||||
|
@ -38,13 +38,13 @@ Object {
|
|||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo.js/originalSource",
|
||||
"sourceId": "foo.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
|
@ -69,13 +69,13 @@ Object {
|
|||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo/originalSource",
|
||||
"sourceId": "foo",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo",
|
||||
},
|
||||
|
@ -100,13 +100,13 @@ Object {
|
|||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo2/originalSource",
|
||||
"sourceId": "foo2",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo2",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo2",
|
||||
},
|
||||
|
|
|
@ -35,7 +35,8 @@ const threadClient = {
|
|||
getFrameScopes: async () => {},
|
||||
evaluate: async expression => ({ result: evaluationResult[expression] }),
|
||||
evaluateExpressions: async expressions =>
|
||||
expressions.map(expression => ({ result: evaluationResult[expression] }))
|
||||
expressions.map(expression => ({ result: evaluationResult[expression] })),
|
||||
getBreakpointPositions: async () => ({})
|
||||
};
|
||||
|
||||
const sourceMaps = {
|
||||
|
@ -43,7 +44,8 @@ const sourceMaps = {
|
|||
id,
|
||||
text: sourceTexts[id],
|
||||
contentType: "text/javascript"
|
||||
})
|
||||
}),
|
||||
getGeneratedRangesForOriginal: async () => []
|
||||
};
|
||||
|
||||
const sourceTexts = {
|
||||
|
|
|
@ -11,12 +11,12 @@ export function mockPendingBreakpoint(overrides: Object = {}) {
|
|||
sourceId: "",
|
||||
sourceUrl: sourceUrl || "http://localhost:8000/examples/bar.js",
|
||||
line: line || 5,
|
||||
column: column || undefined
|
||||
column: column || 1
|
||||
},
|
||||
generatedLocation: {
|
||||
sourceUrl: sourceUrl || "http://localhost:8000/examples/bar.js",
|
||||
line: line || 5,
|
||||
column: column || undefined
|
||||
column: column || 1
|
||||
},
|
||||
astLocation: {
|
||||
name: undefined,
|
||||
|
|
|
@ -76,5 +76,6 @@ export const sourceThreadClient = {
|
|||
},
|
||||
threadClient: async () => {},
|
||||
getFrameScopes: async () => {},
|
||||
evaluateExpressions: async () => {}
|
||||
evaluateExpressions: async () => {},
|
||||
getBreakpointPositions: async () => ({})
|
||||
};
|
||||
|
|
|
@ -23,11 +23,11 @@ const {
|
|||
} = selectors;
|
||||
|
||||
const threadClient = {
|
||||
sourceContents: () =>
|
||||
Promise.resolve({
|
||||
source: "function foo1() {\n const foo = 5; return foo;\n}",
|
||||
contentType: "text/javascript"
|
||||
})
|
||||
sourceContents: async () => ({
|
||||
source: "function foo1() {\n const foo = 5; return foo;\n}",
|
||||
contentType: "text/javascript"
|
||||
}),
|
||||
getBreakpointPositions: async () => ({})
|
||||
};
|
||||
|
||||
describe("navigation", () => {
|
||||
|
|
|
@ -47,13 +47,31 @@ import {
|
|||
waitForState
|
||||
} from "../../utils/test-head";
|
||||
|
||||
import sourceMaps from "devtools-source-map";
|
||||
|
||||
import { makePendingLocationId } from "../../utils/breakpoint";
|
||||
function mockClient(bpPos = {}) {
|
||||
return {
|
||||
...simpleMockThreadClient,
|
||||
getBreakpointPositions: async () => bpPos
|
||||
};
|
||||
}
|
||||
|
||||
function mockSourceMaps() {
|
||||
return {
|
||||
...sourceMaps,
|
||||
getGeneratedRangesForOriginal: async () => [
|
||||
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
describe("when adding breakpoints", () => {
|
||||
it("a corresponding pending breakpoint should be added", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
|
||||
const source = makeOriginalSource("foo.js");
|
||||
|
@ -86,8 +104,9 @@ describe("when adding breakpoints", () => {
|
|||
|
||||
it("add a corresponding pendingBreakpoint for each addition", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
|
||||
const source1 = makeOriginalSource("foo");
|
||||
|
@ -106,14 +125,19 @@ describe("when adding breakpoints", () => {
|
|||
await dispatch(actions.addBreakpoint(breakpoint2.location));
|
||||
|
||||
const pendingBps = selectors.getPendingBreakpoints(getState());
|
||||
|
||||
// NOTE the sourceId should be `foo2/originalSource`, but is `foo2`
|
||||
// because we do not have a real source map for `getOriginalLocation`
|
||||
// to map.
|
||||
expect(pendingBps[breakpointLocationId1]).toMatchSnapshot();
|
||||
expect(pendingBps[breakpointLocationId2]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("hidden breakponts do not create pending bps", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
|
||||
const source = makeOriginalSource("foo");
|
||||
|
@ -131,8 +155,9 @@ describe("when adding breakpoints", () => {
|
|||
|
||||
it("remove a corresponding pending breakpoint when deleting", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
|
||||
await dispatch(actions.newSource(makeSource("foo")));
|
||||
|
@ -161,8 +186,9 @@ describe("when adding breakpoints", () => {
|
|||
describe("when changing an existing breakpoint", () => {
|
||||
it("updates corresponding pendingBreakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bp = generateBreakpoint("foo");
|
||||
const id = makePendingLocationId(bp.location);
|
||||
|
@ -183,8 +209,9 @@ describe("when changing an existing breakpoint", () => {
|
|||
|
||||
it("if disabled, updates corresponding pendingBreakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bp = generateBreakpoint("foo");
|
||||
const id = makePendingLocationId(bp.location);
|
||||
|
@ -204,8 +231,9 @@ describe("when changing an existing breakpoint", () => {
|
|||
|
||||
it("does not delete the pre-existing pendingBreakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bp = generateBreakpoint("foo.js");
|
||||
|
||||
|
@ -229,8 +257,9 @@ describe("when changing an existing breakpoint", () => {
|
|||
describe("initializing when pending breakpoints exist in prefs", () => {
|
||||
it("syncs pending breakpoints", async () => {
|
||||
const { getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bps = selectors.getPendingBreakpoints(getState());
|
||||
expect(bps).toMatchSnapshot();
|
||||
|
@ -238,8 +267,9 @@ describe("initializing when pending breakpoints exist in prefs", () => {
|
|||
|
||||
it("re-adding breakpoints update existing pending breakpoints", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bar = generateBreakpoint("bar.js");
|
||||
|
||||
|
@ -257,8 +287,9 @@ describe("initializing when pending breakpoints exist in prefs", () => {
|
|||
|
||||
it("adding bps doesn't remove existing pending breakpoints", async () => {
|
||||
const { dispatch, getState } = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState()
|
||||
mockClient({ "5": [0] }),
|
||||
loadInitialState(),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const bp = generateBreakpoint("foo.js");
|
||||
|
||||
|
@ -277,8 +308,9 @@ describe("initializing when pending breakpoints exist in prefs", () => {
|
|||
describe("initializing with disabled pending breakpoints in prefs", () => {
|
||||
it("syncs breakpoints with pending breakpoints", async () => {
|
||||
const store = createStore(
|
||||
simpleMockThreadClient,
|
||||
loadInitialState({ disabled: true })
|
||||
mockClient({ "5": [1] }),
|
||||
loadInitialState({ disabled: true }),
|
||||
mockSourceMaps()
|
||||
);
|
||||
|
||||
const { getState, dispatch } = store;
|
||||
|
@ -295,7 +327,7 @@ describe("initializing with disabled pending breakpoints in prefs", () => {
|
|||
|
||||
const bp = selectors.getBreakpointForLocation(getState(), {
|
||||
line: 5,
|
||||
column: undefined,
|
||||
column: 1,
|
||||
sourceUrl: source.url,
|
||||
sourceId: source.id
|
||||
});
|
||||
|
@ -309,7 +341,11 @@ describe("initializing with disabled pending breakpoints in prefs", () => {
|
|||
|
||||
describe("adding sources", () => {
|
||||
it("corresponding breakpoints are added for a single source", async () => {
|
||||
const store = createStore(simpleMockThreadClient, loadInitialState());
|
||||
const store = createStore(
|
||||
mockClient({ "5": [1] }),
|
||||
loadInitialState({ disabled: true }),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
||||
|
@ -327,7 +363,7 @@ describe("adding sources", () => {
|
|||
|
||||
it("corresponding breakpoints are added to the original source", async () => {
|
||||
const source = makeOriginalSource("bar.js", { sourceMapURL: "foo" });
|
||||
const store = createStore(simpleMockThreadClient, loadInitialState(), {
|
||||
const store = createStore(mockClient({ "5": [1] }), loadInitialState(), {
|
||||
getOriginalURLs: async () => [source.url],
|
||||
getOriginalSourceText: async () => ({ source: "" }),
|
||||
getGeneratedLocation: async (location, _source) => ({
|
||||
|
@ -335,7 +371,10 @@ describe("adding sources", () => {
|
|||
column: location.column,
|
||||
sourceId: _source.id
|
||||
}),
|
||||
getOriginalLocation: async location => location
|
||||
getOriginalLocation: async location => location,
|
||||
getGeneratedRangesForOriginal: async () => [
|
||||
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } }
|
||||
]
|
||||
});
|
||||
|
||||
const { getState, dispatch } = store;
|
||||
|
@ -351,7 +390,11 @@ describe("adding sources", () => {
|
|||
});
|
||||
|
||||
it("add corresponding breakpoints for multiple sources", async () => {
|
||||
const store = createStore(simpleMockThreadClient, loadInitialState());
|
||||
const store = createStore(
|
||||
mockClient({ "5": [1] }),
|
||||
loadInitialState({ disabled: true }),
|
||||
mockSourceMaps()
|
||||
);
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
||||
|
|
|
@ -18,41 +18,30 @@ const {
|
|||
getTextSearchStatus
|
||||
} = selectors;
|
||||
|
||||
const threadClient = {
|
||||
sourceContents: function({ source }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
switch (source) {
|
||||
case "foo1":
|
||||
resolve({
|
||||
source: "function foo1() {\n const foo = 5; return foo;\n}",
|
||||
contentType: "text/javascript"
|
||||
});
|
||||
break;
|
||||
case "foo2":
|
||||
resolve({
|
||||
source: "function foo2(x, y) {\n return x + y;\n}",
|
||||
contentType: "text/javascript"
|
||||
});
|
||||
break;
|
||||
case "bar":
|
||||
resolve({
|
||||
source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
|
||||
contentType: "text/javascript"
|
||||
});
|
||||
break;
|
||||
case "bar:formatted":
|
||||
resolve({
|
||||
source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
|
||||
contentType: "text/javascript"
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
reject(`unknown source: ${source}`);
|
||||
});
|
||||
const sources = {
|
||||
foo1: {
|
||||
source: "function foo1() {\n const foo = 5; return foo;\n}",
|
||||
contentType: "text/javascript"
|
||||
},
|
||||
foo2: {
|
||||
source: "function foo2(x, y) {\n return x + y;\n}",
|
||||
contentType: "text/javascript"
|
||||
},
|
||||
bar: {
|
||||
source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
|
||||
contentType: "text/javascript"
|
||||
},
|
||||
"bar:formatted": {
|
||||
source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
|
||||
contentType: "text/javascript"
|
||||
}
|
||||
};
|
||||
|
||||
const threadClient = {
|
||||
sourceContents: async ({ source }) => sources[source],
|
||||
getBreakpointPositions: async () => ({})
|
||||
};
|
||||
|
||||
describe("project text search", () => {
|
||||
it("should add a project text search query", () => {
|
||||
const { dispatch, getState } = createStore();
|
||||
|
@ -87,7 +76,8 @@ describe("project text search", () => {
|
|||
source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
|
||||
contentType: "text/javascript"
|
||||
}),
|
||||
getOriginalURLs: async () => [source2.url]
|
||||
getOriginalURLs: async () => [source2.url],
|
||||
getGeneratedRangesForOriginal: async () => []
|
||||
};
|
||||
|
||||
const { dispatch, getState } = createStore(threadClient, {}, mockMaps);
|
||||
|
|
|
@ -10,7 +10,7 @@ import type { ThunkArgs } from "../../types";
|
|||
|
||||
const blacklist = [
|
||||
"SET_POPUP_OBJECT_PROPERTIES",
|
||||
"SET_PAUSE_POINTS",
|
||||
"ADD_BREAKPOINT_POSITIONS",
|
||||
"SET_SYMBOLS",
|
||||
"OUT_OF_SCOPE_LOCATIONS",
|
||||
"MAP_SCOPES",
|
||||
|
@ -18,7 +18,9 @@ const blacklist = [
|
|||
"ADD_SCOPES",
|
||||
"IN_SCOPE_LINES",
|
||||
"REMOVE_BREAKPOINT",
|
||||
"NODE_PROPERTIES_LOADED"
|
||||
"NODE_PROPERTIES_LOADED",
|
||||
"SET_FOCUSED_SOURCE_ITEM",
|
||||
"NODE_EXPAND"
|
||||
];
|
||||
|
||||
function cloneAction(action: any) {
|
||||
|
|
|
@ -12,12 +12,14 @@ import type {
|
|||
ActorId,
|
||||
BreakpointLocation,
|
||||
BreakpointOptions,
|
||||
PendingLocation,
|
||||
EventListenerBreakpoints,
|
||||
Frame,
|
||||
FrameId,
|
||||
Script,
|
||||
SourceId,
|
||||
SourceActor,
|
||||
Source,
|
||||
Worker,
|
||||
Range
|
||||
} from "../../types";
|
||||
|
@ -175,9 +177,10 @@ function removeXHRBreakpoint(path: string, method: string) {
|
|||
|
||||
// Get the string key to use for a breakpoint location.
|
||||
// See also duplicate code in breakpoint-actor-map.js :(
|
||||
function locationKey(location) {
|
||||
const { sourceUrl, sourceId, line, column } = location;
|
||||
return `${(sourceUrl: any)}:${(sourceId: any)}:${line}:${(column: any)}`;
|
||||
function locationKey(location: BreakpointLocation) {
|
||||
const { sourceUrl, line, column } = location;
|
||||
const sourceId = location.sourceId || "";
|
||||
return `${(sourceUrl: any)}:${sourceId}:${line}:${(column: any)}`;
|
||||
}
|
||||
|
||||
function waitForWorkers(shouldWait: boolean) {
|
||||
|
@ -200,8 +203,8 @@ async function setBreakpoint(
|
|||
await forEachWorkerThread(thread => thread.setBreakpoint(location, options));
|
||||
}
|
||||
|
||||
async function removeBreakpoint(location: BreakpointLocation) {
|
||||
delete breakpoints[locationKey(location)];
|
||||
async function removeBreakpoint(location: PendingLocation) {
|
||||
delete breakpoints[locationKey((location: any))];
|
||||
await threadClient.removeBreakpoint(location);
|
||||
|
||||
// Remove breakpoints without waiting for the thread to respond, for the same
|
||||
|
@ -405,9 +408,10 @@ function getMainThread() {
|
|||
}
|
||||
|
||||
async function getBreakpointPositions(
|
||||
sourceActor: SourceActor,
|
||||
source: Source,
|
||||
range: ?Range
|
||||
): Promise<{ [string]: number[] }> {
|
||||
const sourceActor = source.actors[0];
|
||||
const { thread, actor } = sourceActor;
|
||||
const sourceThreadClient = lookupThreadClient(thread);
|
||||
const sourceClient = sourceThreadClient.source({ actor });
|
||||
|
|
|
@ -18,6 +18,7 @@ import type {
|
|||
Script,
|
||||
Source,
|
||||
Pause,
|
||||
PendingLocation,
|
||||
Frame,
|
||||
SourceId,
|
||||
Worker,
|
||||
|
@ -343,7 +344,7 @@ export type ThreadClient = {
|
|||
pauseGrip: (Grip | Function) => ObjectClient,
|
||||
pauseOnExceptions: (boolean, boolean) => Promise<*>,
|
||||
setBreakpoint: (BreakpointLocation, BreakpointOptions) => Promise<*>,
|
||||
removeBreakpoint: BreakpointLocation => Promise<*>,
|
||||
removeBreakpoint: PendingLocation => Promise<*>,
|
||||
setXHRBreakpoint: (path: string, method: string) => Promise<boolean>,
|
||||
removeXHRBreakpoint: (path: string, method: string) => Promise<boolean>,
|
||||
interrupt: () => Promise<*>,
|
||||
|
|
|
@ -11,7 +11,10 @@ import BreakpointsContextMenu from "../BreakpointsContextMenu";
|
|||
import { createBreakpoint } from "../../../../utils/breakpoint";
|
||||
import { buildMenu } from "devtools-contextmenu";
|
||||
|
||||
import { makeMockSource } from "../../../../utils/test-mockup";
|
||||
import {
|
||||
makeMockSource,
|
||||
makeMappedLocation
|
||||
} from "../../../../utils/test-mockup";
|
||||
|
||||
jest.mock("devtools-contextmenu");
|
||||
|
||||
|
@ -24,12 +27,12 @@ function render(disabled = false) {
|
|||
function generateDefaults(disabled) {
|
||||
const breakpoints = [
|
||||
createBreakpoint(
|
||||
{
|
||||
makeMappedLocation({
|
||||
line: 1,
|
||||
column: undefined,
|
||||
sourceId: "source-https://example.com/main.js",
|
||||
sourceUrl: "https://example.com/main.js"
|
||||
},
|
||||
}),
|
||||
{
|
||||
id: "https://example.com/main.js:1:",
|
||||
disabled: disabled,
|
||||
|
@ -41,12 +44,12 @@ function generateDefaults(disabled) {
|
|||
}
|
||||
),
|
||||
createBreakpoint(
|
||||
{
|
||||
makeMappedLocation({
|
||||
line: 2,
|
||||
column: undefined,
|
||||
sourceId: "source-https://example.com/main.js",
|
||||
sourceUrl: "https://example.com/main.js"
|
||||
},
|
||||
}),
|
||||
{
|
||||
id: "https://example.com/main.js:2:",
|
||||
disabled: disabled,
|
||||
|
@ -56,12 +59,12 @@ function generateDefaults(disabled) {
|
|||
}
|
||||
),
|
||||
createBreakpoint(
|
||||
{
|
||||
makeMappedLocation({
|
||||
line: 3,
|
||||
column: undefined,
|
||||
sourceId: "source-https://example.com/main.js",
|
||||
sourceUrl: "https://example.com/main.js"
|
||||
},
|
||||
}),
|
||||
{
|
||||
id: "https://example.com/main.js:3:",
|
||||
disabled: disabled,
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
} from "../breakpoints";
|
||||
|
||||
import { createBreakpoint } from "../../utils/breakpoint";
|
||||
import { makeMappedLocation } from "../../utils/test-mockup";
|
||||
|
||||
function initializeStateWith(data) {
|
||||
const state = initialBreakpointsState();
|
||||
|
@ -24,12 +25,15 @@ describe("Breakpoints Selectors", () => {
|
|||
it("it gets a breakpoint for an original source", () => {
|
||||
const sourceId = "server1.conn1.child1/source1/originalSource";
|
||||
const matchingBreakpoints = {
|
||||
id1: createBreakpoint({ line: 1, sourceId: sourceId }, { options: {} })
|
||||
id1: createBreakpoint(
|
||||
makeMappedLocation({ line: 1, sourceId: sourceId }),
|
||||
{ options: {} }
|
||||
)
|
||||
};
|
||||
|
||||
const otherBreakpoints = {
|
||||
id2: createBreakpoint(
|
||||
{ line: 1, sourceId: "not-this-source" },
|
||||
makeMappedLocation({ line: 1, sourceId: "not-this-source" }),
|
||||
{ options: {} }
|
||||
)
|
||||
};
|
||||
|
@ -54,12 +58,11 @@ describe("Breakpoints Selectors", () => {
|
|||
const generatedSourceId = "random-source";
|
||||
const matchingBreakpoints = {
|
||||
id1: createBreakpoint(
|
||||
makeMappedLocation(
|
||||
{ line: 1, sourceId: "original-source-id-1" },
|
||||
{ line: 1, sourceId: generatedSourceId }
|
||||
),
|
||||
{
|
||||
line: 1,
|
||||
sourceId: "original-source-id-1"
|
||||
},
|
||||
{
|
||||
generatedLocation: { line: 1, sourceId: generatedSourceId },
|
||||
options: {}
|
||||
}
|
||||
)
|
||||
|
@ -67,12 +70,11 @@ describe("Breakpoints Selectors", () => {
|
|||
|
||||
const otherBreakpoints = {
|
||||
id2: createBreakpoint(
|
||||
makeMappedLocation(
|
||||
{ line: 1, sourceId: "original-source-id-2" },
|
||||
{ line: 1, sourceId: "not-this-source" }
|
||||
),
|
||||
{
|
||||
line: 1,
|
||||
sourceId: "original-source-id-2"
|
||||
},
|
||||
{
|
||||
generatedLocation: { line: 1, sourceId: "not-this-source" },
|
||||
options: {}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -28,7 +28,11 @@ function getBreakpointsForSource(
|
|||
breakpoints: Breakpoint[]
|
||||
) {
|
||||
return breakpoints
|
||||
.sort((a, b) => a.location.line - b.location.line)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
getSelectedLocation(a, selectedSource).line -
|
||||
getSelectedLocation(b, selectedSource).line
|
||||
)
|
||||
.filter(
|
||||
bp =>
|
||||
!bp.options.hidden &&
|
||||
|
@ -42,9 +46,12 @@ function getBreakpointsForSource(
|
|||
|
||||
function findBreakpointSources(
|
||||
sources: SourcesMap,
|
||||
breakpoints: Breakpoint[]
|
||||
breakpoints: Breakpoint[],
|
||||
selectedSource: ?Source
|
||||
): Source[] {
|
||||
const sourceIds: string[] = uniq(breakpoints.map(bp => bp.location.sourceId));
|
||||
const sourceIds: string[] = uniq(
|
||||
breakpoints.map(bp => getSelectedLocation(bp, selectedSource).sourceId)
|
||||
);
|
||||
|
||||
const breakpointSources = sourceIds
|
||||
.map(id => sources[id])
|
||||
|
@ -58,7 +65,7 @@ export const getBreakpointSources: Selector<BreakpointSources> = createSelector(
|
|||
getSources,
|
||||
getSelectedSource,
|
||||
(breakpoints: Breakpoint[], sources: SourcesMap, selectedSource: ?Source) =>
|
||||
findBreakpointSources(sources, breakpoints)
|
||||
findBreakpointSources(sources, breakpoints, selectedSource)
|
||||
.map(source => ({
|
||||
source,
|
||||
breakpoints: getBreakpointsForSource(
|
||||
|
|
|
@ -30,8 +30,7 @@ export {
|
|||
} from "./breakpointAtLocation";
|
||||
export {
|
||||
getVisibleBreakpoints,
|
||||
getFirstVisibleBreakpoints,
|
||||
getFirstVisibleBreakpointPosition
|
||||
getFirstVisibleBreakpoints
|
||||
} from "./visibleBreakpoints";
|
||||
export { inComponent } from "./inComponent";
|
||||
export { isSelectedFrameVisible } from "./isSelectedFrameVisible";
|
||||
|
@ -39,7 +38,7 @@ export { getCallStackFrames } from "./getCallStackFrames";
|
|||
export { getVisibleSelectedFrame } from "./visibleSelectedFrame";
|
||||
export { getBreakpointSources } from "./breakpointSources";
|
||||
export { getXHRBreakpoints, shouldPauseOnAnyXHR } from "./breakpoints";
|
||||
export { visibleColumnBreakpoints } from "./visibleColumnBreakpoints";
|
||||
export * from "./visibleColumnBreakpoints";
|
||||
|
||||
import { objectInspector } from "devtools-reps";
|
||||
|
||||
|
|
|
@ -7,22 +7,14 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
import {
|
||||
getBreakpointsList,
|
||||
getBreakpointPositionsForLine
|
||||
} from "../reducers/breakpoints";
|
||||
import { getBreakpointsList } from "../reducers/breakpoints";
|
||||
import { getSelectedSource } from "../reducers/sources";
|
||||
|
||||
import { sortBreakpoints } from "../utils/breakpoint";
|
||||
import { sortSelectedBreakpoints } from "../utils/breakpoint";
|
||||
import { getSelectedLocation } from "../utils/source-maps";
|
||||
|
||||
import type { Breakpoint, Source, SourceLocation } from "../types";
|
||||
import type { Selector, State } from "../reducers/types";
|
||||
|
||||
function isVisible(breakpoint: Breakpoint, selectedSource: Source) {
|
||||
const location = getSelectedLocation(breakpoint, selectedSource);
|
||||
return location.sourceId === selectedSource.id;
|
||||
}
|
||||
import type { Breakpoint, Source } from "../types";
|
||||
import type { Selector } from "../reducers/types";
|
||||
|
||||
/*
|
||||
* Finds the breakpoints, which appear in the selected source.
|
||||
|
@ -31,35 +23,34 @@ export const getVisibleBreakpoints: Selector<?(Breakpoint[])> = createSelector(
|
|||
getSelectedSource,
|
||||
getBreakpointsList,
|
||||
(selectedSource: ?Source, breakpoints: Breakpoint[]) => {
|
||||
if (selectedSource == null) {
|
||||
if (!selectedSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// FIXME: Even though selectedSource is checked above, it fails type
|
||||
// checking for isVisible
|
||||
const source: Source = selectedSource;
|
||||
return breakpoints.filter(bp => isVisible(bp, source));
|
||||
return breakpoints.filter(
|
||||
bp =>
|
||||
selectedSource &&
|
||||
getSelectedLocation(bp, selectedSource).sourceId === selectedSource.id
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export function getFirstVisibleBreakpointPosition(
|
||||
state: State,
|
||||
location: SourceLocation
|
||||
): ?SourceLocation {
|
||||
const { sourceId, line } = location;
|
||||
const positions = getBreakpointPositionsForLine(state, sourceId, line);
|
||||
return positions && positions[0].location;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the first breakpoint per line, which appear in the selected source.
|
||||
*/
|
||||
export const getFirstVisibleBreakpoints: Selector<
|
||||
Breakpoint[]
|
||||
> = createSelector(getVisibleBreakpoints, breakpoints => {
|
||||
if (!breakpoints) {
|
||||
return [];
|
||||
}
|
||||
> = createSelector(
|
||||
getVisibleBreakpoints,
|
||||
getSelectedSource,
|
||||
(breakpoints, selectedSource) => {
|
||||
if (!breakpoints || !selectedSource) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return (uniqBy(sortBreakpoints(breakpoints), bp => bp.location.line): any);
|
||||
});
|
||||
return (uniqBy(
|
||||
sortSelectedBreakpoints(breakpoints, selectedSource),
|
||||
bp => getSelectedLocation(bp, selectedSource).line
|
||||
): any);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -3,24 +3,28 @@
|
|||
* 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 { groupBy, sortedUniqBy } from "lodash";
|
||||
import { groupBy } from "lodash";
|
||||
import { createSelector } from "reselect";
|
||||
|
||||
import {
|
||||
getViewport,
|
||||
getSource,
|
||||
getSelectedSource,
|
||||
getBreakpointPositions
|
||||
getBreakpointPositions,
|
||||
getBreakpointPositionsForSource
|
||||
} from "../selectors";
|
||||
import { getVisibleBreakpoints } from "./visibleBreakpoints";
|
||||
import { makeBreakpointId } from "../utils/breakpoint";
|
||||
import type { Selector } from "../reducers/types";
|
||||
import { getSelectedLocation } from "../utils/source-maps";
|
||||
import type { Selector, State } from "../reducers/types";
|
||||
|
||||
import type {
|
||||
SourceLocation,
|
||||
PartialPosition,
|
||||
Breakpoint,
|
||||
Range,
|
||||
BreakpointPositions
|
||||
BreakpointPositions,
|
||||
BreakpointPosition,
|
||||
Source
|
||||
} from "../types";
|
||||
|
||||
export type ColumnBreakpoint = {|
|
||||
|
@ -44,13 +48,20 @@ function inViewport(viewport, location) {
|
|||
return viewport && contains(location, viewport);
|
||||
}
|
||||
|
||||
function groupBreakpoints(breakpoints) {
|
||||
function groupBreakpoints(breakpoints, selectedSource) {
|
||||
if (!breakpoints) {
|
||||
return {};
|
||||
}
|
||||
const map: any = groupBy(breakpoints, ({ location }) => location.line);
|
||||
const map: any = groupBy(
|
||||
breakpoints,
|
||||
breakpoint => getSelectedLocation(breakpoint, selectedSource).line
|
||||
);
|
||||
|
||||
for (const line in map) {
|
||||
map[line] = groupBy(map[line], ({ location }) => location.column);
|
||||
map[line] = groupBy(
|
||||
map[line],
|
||||
breakpoint => getSelectedLocation(breakpoint, selectedSource).column
|
||||
);
|
||||
}
|
||||
|
||||
return map;
|
||||
|
@ -65,70 +76,74 @@ function findBreakpoint(location, breakpointMap) {
|
|||
}
|
||||
}
|
||||
|
||||
function getLineCount(columnBreakpoints) {
|
||||
function filterByLineCount(positions, selectedSource) {
|
||||
const lineCount = {};
|
||||
columnBreakpoints.forEach(({ location: { line } }) => {
|
||||
|
||||
for (const breakpoint of positions) {
|
||||
const { line } = getSelectedLocation(breakpoint, selectedSource);
|
||||
if (!lineCount[line]) {
|
||||
lineCount[line] = 0;
|
||||
}
|
||||
|
||||
lineCount[line] = lineCount[line] + 1;
|
||||
});
|
||||
}
|
||||
|
||||
return lineCount;
|
||||
return positions.filter(
|
||||
breakpoint =>
|
||||
lineCount[getSelectedLocation(breakpoint, selectedSource).line] > 1
|
||||
);
|
||||
}
|
||||
|
||||
export function formatColumnBreakpoints(columnBreakpoints: ColumnBreakpoints) {
|
||||
console.log(
|
||||
"Column Breakpoints\n\n",
|
||||
columnBreakpoints
|
||||
.map(
|
||||
({ location, breakpoint }) =>
|
||||
`(${location.line}, ${location.column || ""}) ${
|
||||
breakpoint && breakpoint.disabled ? "disabled" : ""
|
||||
}`
|
||||
)
|
||||
.join("\n")
|
||||
);
|
||||
function filterVisible(positions, selectedSource, viewport) {
|
||||
return positions.filter(columnBreakpoint => {
|
||||
const location = getSelectedLocation(columnBreakpoint, selectedSource);
|
||||
return inViewport(viewport, location);
|
||||
});
|
||||
}
|
||||
|
||||
function filterByBreakpoints(positions, selectedSource, breakpointMap) {
|
||||
return positions.filter(position => {
|
||||
const location = getSelectedLocation(position, selectedSource);
|
||||
return breakpointMap[location.line];
|
||||
});
|
||||
}
|
||||
|
||||
function formatPositions(
|
||||
positions: BreakpointPositions,
|
||||
selectedSource,
|
||||
breakpointMap
|
||||
) {
|
||||
return (positions: any).map((position: BreakpointPosition) => {
|
||||
const location = getSelectedLocation(position, selectedSource);
|
||||
return {
|
||||
location,
|
||||
breakpoint: findBreakpoint(location, breakpointMap)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function getColumnBreakpoints(
|
||||
positions: ?BreakpointPositions,
|
||||
breakpoints: ?(Breakpoint[]),
|
||||
viewport: Range
|
||||
viewport: Range,
|
||||
selectedSource: ?Source
|
||||
) {
|
||||
if (!positions) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const breakpointMap = groupBreakpoints(breakpoints);
|
||||
|
||||
// We only want to show a column breakpoint if several conditions are matched
|
||||
// 1. there is a breakpoint on that line
|
||||
// 2. the position is in the current viewport
|
||||
// 4. it is the first breakpoint to appear at that generated location
|
||||
// 5. there is atleast one other breakpoint on that line
|
||||
// - it is the first breakpoint to appear at an the original location
|
||||
// - the position is in the current viewport
|
||||
// - there is atleast one other breakpoint on that line
|
||||
// - there is a breakpoint on that line
|
||||
const breakpointMap = groupBreakpoints(breakpoints, selectedSource);
|
||||
|
||||
let columnBreakpoints = positions.filter(
|
||||
({ location }) =>
|
||||
breakpointMap[location.line] && inViewport(viewport, location)
|
||||
);
|
||||
positions = filterByLineCount(positions, selectedSource);
|
||||
positions = filterVisible(positions, selectedSource, viewport);
|
||||
positions = filterByBreakpoints(positions, selectedSource, breakpointMap);
|
||||
|
||||
// 4. Only show one column breakpoint per generated location
|
||||
columnBreakpoints = sortedUniqBy(columnBreakpoints, ({ generatedLocation }) =>
|
||||
makeBreakpointId(generatedLocation)
|
||||
);
|
||||
|
||||
// 5. Check that there is atleast one other possible breakpoint on the line
|
||||
const lineCount = getLineCount(columnBreakpoints);
|
||||
columnBreakpoints = columnBreakpoints.filter(
|
||||
({ location: { line } }) => lineCount[line] > 1
|
||||
);
|
||||
|
||||
return (columnBreakpoints: any).map(({ location }) => ({
|
||||
location,
|
||||
breakpoint: findBreakpoint(location, breakpointMap)
|
||||
}));
|
||||
return formatPositions(positions, selectedSource, breakpointMap);
|
||||
}
|
||||
|
||||
const getVisibleBreakpointPositions = createSelector(
|
||||
|
@ -146,3 +161,35 @@ export const visibleColumnBreakpoints: Selector<
|
|||
getSelectedSource,
|
||||
getColumnBreakpoints
|
||||
);
|
||||
|
||||
export function getFirstBreakpointPosition(
|
||||
state: State,
|
||||
{ line, sourceId }: SourceLocation
|
||||
) {
|
||||
const positions = getBreakpointPositionsForSource(state, sourceId);
|
||||
const source = getSource(state, sourceId);
|
||||
|
||||
if (!source || !positions) {
|
||||
return;
|
||||
}
|
||||
|
||||
return positions.find(
|
||||
position => getSelectedLocation(position, source).line == line
|
||||
);
|
||||
}
|
||||
|
||||
export function getFirstVisibleBreakpointPosition(
|
||||
state: State,
|
||||
{ line }: SourceLocation
|
||||
) {
|
||||
const positions = getVisibleBreakpointPositions(state);
|
||||
const selectedSource = getSelectedSource(state);
|
||||
|
||||
if (!selectedSource || !positions) {
|
||||
return;
|
||||
}
|
||||
|
||||
return positions.find(
|
||||
position => getSelectedLocation(position, selectedSource).line == line
|
||||
);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ export function getASTLocation(
|
|||
return { name: undefined, offset: location, index: 0 };
|
||||
}
|
||||
|
||||
export async function findScopeByName(
|
||||
export async function findFunctionByName(
|
||||
source: Source,
|
||||
name: ?string,
|
||||
index: number
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// @flow
|
||||
|
||||
/* 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 { comparePosition } from "../location";
|
||||
import type {
|
||||
BreakpointPositions,
|
||||
SourceLocation,
|
||||
Position
|
||||
} from "../../types";
|
||||
|
||||
export function findPosition(
|
||||
positions: ?BreakpointPositions,
|
||||
location: Position | SourceLocation
|
||||
) {
|
||||
if (!positions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return positions.find(pos => comparePosition(pos.location, location));
|
||||
}
|
|
@ -13,7 +13,8 @@ import assert from "../assert";
|
|||
import { features } from "../prefs";
|
||||
import { getSelectedLocation } from "../source-maps";
|
||||
|
||||
export { getASTLocation, findScopeByName } from "./astBreakpointLocation";
|
||||
export * from "./astBreakpointLocation";
|
||||
export * from "./breakpointPositions";
|
||||
|
||||
import type {
|
||||
Source,
|
||||
|
@ -23,7 +24,8 @@ import type {
|
|||
PendingLocation,
|
||||
Breakpoint,
|
||||
BreakpointLocation,
|
||||
PendingBreakpoint
|
||||
PendingBreakpoint,
|
||||
MappedLocation
|
||||
} from "../../types";
|
||||
|
||||
import type { State } from "../../reducers/types";
|
||||
|
@ -39,15 +41,6 @@ export function firstString(...args: string[]) {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function locationMoved(
|
||||
location: SourceLocation,
|
||||
newLocation: SourceLocation
|
||||
) {
|
||||
return (
|
||||
location.line !== newLocation.line || location.column !== newLocation.column
|
||||
);
|
||||
}
|
||||
|
||||
// The ID for a Breakpoint is derived from its location in its Source.
|
||||
export function makeBreakpointId(location: SourceLocation) {
|
||||
const { sourceId, line, column } = location;
|
||||
|
@ -164,25 +157,19 @@ export function breakpointExists(state: State, location: SourceLocation) {
|
|||
}
|
||||
|
||||
export function createBreakpoint(
|
||||
location: SourceLocation,
|
||||
mappedLocation: MappedLocation,
|
||||
overrides: Object = {}
|
||||
): Breakpoint {
|
||||
const {
|
||||
disabled,
|
||||
generatedLocation,
|
||||
astLocation,
|
||||
text,
|
||||
originalText,
|
||||
options
|
||||
} = overrides;
|
||||
const { disabled, astLocation, text, originalText, options } = overrides;
|
||||
|
||||
const defaultASTLocation = {
|
||||
name: undefined,
|
||||
offset: location,
|
||||
offset: mappedLocation.location,
|
||||
index: 0
|
||||
};
|
||||
const properties = {
|
||||
id: makeBreakpointId(location),
|
||||
id: makeBreakpointId(mappedLocation.location),
|
||||
...mappedLocation,
|
||||
options: {
|
||||
condition: options.condition || null,
|
||||
logValue: options.logValue || null,
|
||||
|
@ -191,8 +178,6 @@ export function createBreakpoint(
|
|||
disabled: disabled || false,
|
||||
loading: false,
|
||||
astLocation: astLocation || defaultASTLocation,
|
||||
generatedLocation: generatedLocation || location,
|
||||
location,
|
||||
text,
|
||||
originalText
|
||||
};
|
||||
|
|
|
@ -9,5 +9,6 @@ DIRS += [
|
|||
|
||||
DebuggerModules(
|
||||
'astBreakpointLocation.js',
|
||||
'breakpointPositions.js',
|
||||
'index.js',
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import type { SourceLocation, SourceId } from "../types";
|
||||
import type { PartialPosition, SourceLocation, SourceId } from "../types";
|
||||
|
||||
type IncompleteLocation = {
|
||||
sourceId: SourceId,
|
||||
|
@ -13,6 +13,10 @@ type IncompleteLocation = {
|
|||
sourceUrl?: string
|
||||
};
|
||||
|
||||
export function comparePosition(a: ?PartialPosition, b: ?PartialPosition) {
|
||||
return a && b && a.line == b.line && a.column == b.column;
|
||||
}
|
||||
|
||||
export function createLocation({
|
||||
sourceId,
|
||||
line = 1,
|
||||
|
|
|
@ -41,7 +41,6 @@ export async function getGeneratedLocation(
|
|||
|
||||
export async function getOriginalLocation(
|
||||
generatedLocation: SourceLocation,
|
||||
source: Source,
|
||||
sourceMaps: SourceMaps
|
||||
) {
|
||||
if (isOriginalId(generatedLocation.sourceId)) {
|
||||
|
@ -55,6 +54,36 @@ export async function getMappedLocation(
|
|||
state: Object,
|
||||
sourceMaps: Object,
|
||||
location: SourceLocation
|
||||
): Promise<MappedLocation> {
|
||||
const source = getSource(state, location.sourceId);
|
||||
|
||||
if (!source) {
|
||||
throw new Error(`no source ${location.sourceId}`);
|
||||
}
|
||||
|
||||
if (isOriginalId(location.sourceId)) {
|
||||
const generatedLocation = await getGeneratedLocation(
|
||||
state,
|
||||
source,
|
||||
location,
|
||||
sourceMaps
|
||||
);
|
||||
return { location, generatedLocation };
|
||||
}
|
||||
|
||||
const generatedLocation = location;
|
||||
const originalLocation = await sourceMaps.getOriginalLocation(
|
||||
generatedLocation,
|
||||
source
|
||||
);
|
||||
|
||||
return { location: originalLocation, generatedLocation };
|
||||
}
|
||||
|
||||
export async function mapLocation(
|
||||
state: Object,
|
||||
sourceMaps: Object,
|
||||
location: SourceLocation
|
||||
): Promise<SourceLocation> {
|
||||
const source = getSource(state, location.sourceId);
|
||||
|
||||
|
@ -69,10 +98,14 @@ export async function getMappedLocation(
|
|||
return sourceMaps.getOriginalLocation(location, source);
|
||||
}
|
||||
|
||||
export function isOriginalSource(source: ?Source) {
|
||||
return source && isOriginalId(source.id);
|
||||
}
|
||||
|
||||
export function getSelectedLocation(
|
||||
mappedLocation: MappedLocation,
|
||||
selectedSource: ?Source
|
||||
) {
|
||||
): SourceLocation {
|
||||
return selectedSource && isGenerated(selectedSource)
|
||||
? mappedLocation.generatedLocation
|
||||
: mappedLocation.location;
|
||||
|
|
|
@ -45,6 +45,14 @@ function createStore(client: any, initialState: any = {}, sourceMapsMock: any) {
|
|||
newSources: sources => store.dispatch(actions.newSources(sources))
|
||||
});
|
||||
|
||||
store.thunkArgs = () => ({
|
||||
dispatch: store.dispatch,
|
||||
getState: store.getState,
|
||||
client,
|
||||
sourceMaps,
|
||||
panel: {}
|
||||
});
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import type {
|
|||
WasmSource,
|
||||
Source,
|
||||
SourceId,
|
||||
SourceLocation,
|
||||
Why
|
||||
} from "../types";
|
||||
|
||||
|
@ -153,6 +154,14 @@ function makeMockExpression(value: Object): Expression {
|
|||
};
|
||||
}
|
||||
|
||||
export function makeMappedLocation(
|
||||
location: SourceLocation,
|
||||
generatedLocation: ?SourceLocation
|
||||
) {
|
||||
generatedLocation = generatedLocation || location;
|
||||
return { location, generatedLocation };
|
||||
}
|
||||
|
||||
export {
|
||||
makeMockSource,
|
||||
makeMockWasmSource,
|
||||
|
|
|
@ -10,9 +10,12 @@ add_task(async function() {
|
|||
getState
|
||||
} = dbg;
|
||||
|
||||
await selectSource(dbg, "scripts.html");
|
||||
|
||||
// Make sure we can set a top-level breakpoint and it will be hit on
|
||||
// reload.
|
||||
await addBreakpoint(dbg, "scripts.html", 21);
|
||||
|
||||
reload(dbg);
|
||||
|
||||
await waitForDispatch(dbg, "NAVIGATE");
|
||||
|
@ -22,7 +25,7 @@ add_task(async function() {
|
|||
assertPausedLocation(dbg);
|
||||
await resume(dbg);
|
||||
|
||||
// Create an eval script that pauses itself.
|
||||
info('Create an eval script that pauses itself.')
|
||||
invokeInTab("doEval");
|
||||
await waitForPaused(dbg);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ function skipPausing(dbg) {
|
|||
|
||||
add_task(async function() {
|
||||
let dbg = await initDebugger("doc-scripts.html");
|
||||
await selectSource(dbg, "simple3")
|
||||
await addBreakpoint(dbg, "simple3", 2);
|
||||
|
||||
await skipPausing(dbg);
|
||||
|
|
|
@ -2,16 +2,6 @@
|
|||
* 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/>. */
|
||||
|
||||
function findBreakpoint(dbg, url, line, column = 0) {
|
||||
const {
|
||||
selectors: { getBreakpoint },
|
||||
getState
|
||||
} = dbg;
|
||||
const source = findSource(dbg, url);
|
||||
const location = { sourceId: source.id, line, column };
|
||||
return getBreakpoint(getState(), location);
|
||||
}
|
||||
|
||||
function getLineEl(dbg, line) {
|
||||
const lines = dbg.win.document.querySelectorAll(".CodeMirror-code > div");
|
||||
return lines[line - 1];
|
||||
|
@ -116,7 +106,7 @@ async function setLogPoint(dbg, index, value) {
|
|||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html", "simple2");
|
||||
await pushPref("devtools.debugger.features.column-breakpoints", false);
|
||||
await pushPref("devtools.debugger.features.column-breakpoints", true);
|
||||
await pushPref("devtools.debugger.features.log-points", true);
|
||||
|
||||
await selectSource(dbg, "simple2");
|
||||
|
|
|
@ -42,24 +42,24 @@ add_task(async function() {
|
|||
await waitForLoadedSource(dbg, "debugger-statements.html");
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
// resume
|
||||
info("resume");
|
||||
await clickResume(dbg);
|
||||
await waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
// step over
|
||||
info("step over");
|
||||
await clickStepOver(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
// step into
|
||||
info("step into");
|
||||
await clickStepIn(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
// step over
|
||||
info("step over");
|
||||
await clickStepOver(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
// step out
|
||||
info("step out");
|
||||
await clickStepOut(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
});
|
||||
|
|
|
@ -53,12 +53,4 @@ add_task(async function() {
|
|||
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
|
||||
is(getBreakpointCount(getState()), 0, "No breakpoints exist");
|
||||
assertEditorBreakpoint(dbg, 4, false);
|
||||
|
||||
// Ensure that clicking the gutter removes all breakpoints on a given line
|
||||
await addBreakpoint(dbg, source, 4, 0);
|
||||
await addBreakpoint(dbg, source, 4, 1);
|
||||
await addBreakpoint(dbg, source, 4, 2);
|
||||
clickGutter(dbg, 4);
|
||||
await waitForState(dbg, state => dbg.selectors.getBreakpointCount(state) === 0);
|
||||
assertEditorBreakpoint(dbg, 4, false);
|
||||
});
|
||||
|
|
|
@ -18,8 +18,8 @@ add_task(async function() {
|
|||
const simple2 = findSource(dbg, "simple2.js");
|
||||
|
||||
// Set the initial breakpoint.
|
||||
await selectSource(dbg, "simple1");
|
||||
await addBreakpoint(dbg, simple1, 4);
|
||||
ok(!getSelectedSource(getState()), "No selected source");
|
||||
|
||||
// Call the function that we set a breakpoint in.
|
||||
invokeInTab("main");
|
||||
|
@ -43,6 +43,7 @@ add_task(async function() {
|
|||
// Make sure that we can set a breakpoint on a line out of the
|
||||
// viewport, and that pausing there scrolls the editor to it.
|
||||
let longSrc = findSource(dbg, "long.js");
|
||||
await selectSource(dbg, "long.js");
|
||||
await addBreakpoint(dbg, longSrc, 66);
|
||||
|
||||
invokeInTab("testModel");
|
||||
|
|
|
@ -29,6 +29,7 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
|
||||
await navigate(dbg, "doc-scripts.html", "simple1.js");
|
||||
await selectSource(dbg, "simple1");
|
||||
await addBreakpoint(dbg, "simple1.js", 4);
|
||||
invokeInTab("main");
|
||||
await waitForPaused(dbg);
|
||||
|
|
|
@ -22,6 +22,7 @@ add_task(async function() {
|
|||
// Make sure that we can set a breakpoint on a line out of the
|
||||
// viewport, and that pausing there scrolls the editor to it.
|
||||
let longSrc = findSource(dbg, "long.js");
|
||||
await selectSource(dbg, "long.js")
|
||||
await addBreakpoint(dbg, longSrc, 66);
|
||||
invokeInTab("testModel");
|
||||
await waitForPaused(dbg, "long.js");
|
||||
|
|
|
@ -16,7 +16,7 @@ add_task(async function() {
|
|||
|
||||
// this is not implemented yet
|
||||
// assertHighlightLocation(dbg, "math.min.js:formatted", 18);
|
||||
|
||||
// await selectSource(dbg, "math.min.js")
|
||||
await addBreakpoint(dbg, ppSrc, 18);
|
||||
|
||||
invokeInTab("arithmetic");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-react.html", "App.js");
|
||||
|
||||
await selectSource(dbg, "App.js");
|
||||
await addBreakpoint(dbg, "App.js", 11);
|
||||
|
||||
info('Test previewing an immutable Map inside of a react component')
|
||||
|
|
|
@ -28,7 +28,7 @@ add_task(async function() {
|
|||
await waitForSelectedSource(dbg, "sjs_code_reload.sjs");
|
||||
|
||||
const source = findSource(dbg, "sjs_code_reload");
|
||||
const location = { sourceId: source.id, line: 6 };
|
||||
const location = { sourceId: source.id, line: 6, column: 2 };
|
||||
|
||||
await waitForBreakpoint(dbg, location);
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ add_task(async function() {
|
|||
[`aVar === "var3"`, `aLet === "let3"`, `aConst === "const3"`]
|
||||
);
|
||||
|
||||
await evalInConsoleAtPoint(dbg, "webpack3-babel6", "babel-classes", { line: 8, column: 6 }, [
|
||||
await evalInConsoleAtPoint(dbg, "webpack3-babel6", "babel-classes", { line: 8, column: 16 }, [
|
||||
`this.hasOwnProperty("bound")`,
|
||||
]);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ function targetToFlags(target) {
|
|||
const rollupOptimized = isRollup ? "(optimized away)" : null;
|
||||
const webpackImportGetter = isWebpack ? "Getter" : null;
|
||||
const webpack4ImportGetter = isWebpack4 ? "Getter" : null;
|
||||
const maybeLineStart = hasBabel ? col => col : col => 0;
|
||||
const maybeLineStart = col => col;
|
||||
const defaultExport = isWebpack4
|
||||
? name => `${name}()`
|
||||
: name => [name, "(optimized away)"];
|
||||
|
@ -183,7 +183,7 @@ async function testEvalMaps(dbg) {
|
|||
]) {
|
||||
const { defaultExport } = targetToFlags(target);
|
||||
|
||||
await breakpointScopes(dbg, target, "eval-maps", { line: 14, column: 0 }, [
|
||||
await breakpointScopes(dbg, target, "eval-maps", { line: 14, column: 4 }, [
|
||||
"Block",
|
||||
["<this>", "Window"],
|
||||
["three", "5"],
|
||||
|
|
|
@ -26,12 +26,14 @@ add_task(async function() {
|
|||
|
||||
await navigate(dbg, "sourcemaps-reload/doc-sourcemaps-reload.html", "v1.js");
|
||||
|
||||
info('Add initial breakpoint');
|
||||
await selectSource(dbg, "v1.js");
|
||||
await addBreakpoint(dbg, "v1.js", 6);
|
||||
|
||||
let breakpoint = getBreakpoints(dbg)[0];
|
||||
is(breakpoint.location.line, 6);
|
||||
|
||||
info('Reload with a new version of the file');
|
||||
let syncBp = waitForDispatch(dbg, "SYNC_BREAKPOINT");
|
||||
await navigate(dbg, "doc-sourcemaps-reload2.html", "v1.js");
|
||||
|
||||
|
@ -41,10 +43,14 @@ add_task(async function() {
|
|||
is(breakpoint.location.line, 9);
|
||||
is(breakpoint.generatedLocation.line, 73);
|
||||
|
||||
info('Add a second breakpoint');
|
||||
await addBreakpoint(dbg, "v1.js", 13);
|
||||
is(dbg.selectors.getBreakpointCount(dbg.getState()), 2, "No breakpoints");
|
||||
|
||||
|
||||
// NOTE: When we reload, the `foo` function and the
|
||||
// module is no longer 13 lines long
|
||||
info('Reload and observe no breakpoints')
|
||||
syncBp = waitForDispatch(dbg, "SYNC_BREAKPOINT", 2);
|
||||
await navigate(dbg, "doc-sourcemaps-reload3.html", "v1.js");
|
||||
await waitForSource(dbg, "v1");
|
||||
|
|
|
@ -30,18 +30,7 @@ add_task(async function() {
|
|||
"Original source text loaded correctly"
|
||||
);
|
||||
|
||||
// Test that breakpoint sliding is not attempted. The breakpoint
|
||||
// should not move anywhere.
|
||||
await addBreakpoint(dbg, entrySrc, 13);
|
||||
is(getBreakpointCount(getState()), 1, "One breakpoint exists");
|
||||
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
|
||||
"Breakpoint has correct line"
|
||||
);
|
||||
|
||||
await addBreakpoint(dbg, entrySrc, 5);
|
||||
|
||||
await addBreakpoint(dbg, entrySrc, 15, 0);
|
||||
await disableBreakpoint(dbg, entrySrc, 15, 0);
|
||||
|
||||
|
@ -52,11 +41,11 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
await waitForBreakpointCount(dbg, 3);
|
||||
is(getBreakpointCount(getState()), 3, "Three breakpoints exist");
|
||||
await waitForBreakpointCount(dbg, 2);
|
||||
is(getBreakpointCount(getState()), 2, "Three breakpoints exist");
|
||||
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
|
||||
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 15, column: 0 }),
|
||||
"Breakpoint has correct line"
|
||||
);
|
||||
|
||||
|
@ -64,6 +53,7 @@ add_task(async function() {
|
|||
getBreakpoint(getState(), {
|
||||
sourceId: entrySrc.id,
|
||||
line: 15,
|
||||
column: 0,
|
||||
disabled: true
|
||||
}),
|
||||
"Breakpoint has correct line"
|
||||
|
|
|
@ -17,8 +17,9 @@ function assertBreakpointExists(dbg, source, line) {
|
|||
);
|
||||
}
|
||||
|
||||
function assertEditorBreakpoint(dbg, line, shouldExist) {
|
||||
const exists = !!getLineEl(dbg, line).querySelector(".new-breakpoint");
|
||||
async function assertEditorBreakpoint(dbg, line, shouldExist) {
|
||||
const el = await getLineEl(dbg, line);
|
||||
const exists = !!el.querySelector(".new-breakpoint");
|
||||
ok(
|
||||
exists === shouldExist,
|
||||
"Breakpoint " +
|
||||
|
@ -28,13 +29,17 @@ function assertEditorBreakpoint(dbg, line, shouldExist) {
|
|||
);
|
||||
}
|
||||
|
||||
function getLineEl(dbg, line) {
|
||||
const lines = dbg.win.document.querySelectorAll(".CodeMirror-code > div");
|
||||
return lines[line - 1];
|
||||
async function getLineEl(dbg, line) {
|
||||
let el = await codeMirrorGutterElement(dbg, line);
|
||||
while (el && !el.matches(".CodeMirror-code > div")) {
|
||||
el = el.parentElement;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
function clickGutter(dbg, line) {
|
||||
clickElement(dbg, "gutter", line);
|
||||
async function clickGutter(dbg, line) {
|
||||
const el = await codeMirrorGutterElement(dbg, line);
|
||||
clickDOMElement(dbg, el);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -54,11 +59,11 @@ add_task(async function() {
|
|||
|
||||
await selectSource(dbg, bundleSrc);
|
||||
|
||||
await clickGutter(dbg, 13);
|
||||
await clickGutter(dbg, 70);
|
||||
await waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||
assertEditorBreakpoint(dbg, 13, true);
|
||||
assertEditorBreakpoint(dbg, 70, true);
|
||||
|
||||
await clickGutter(dbg, 13);
|
||||
await clickGutter(dbg, 70);
|
||||
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
|
||||
is(getBreakpointCount(getState()), 0, "No breakpoints exists");
|
||||
|
||||
|
|
|
@ -14,13 +14,14 @@ add_task(async function() {
|
|||
// shutting down.
|
||||
dbg.client.waitForWorkers(true);
|
||||
|
||||
await selectSource(dbg, "simple-worker.js");
|
||||
await addBreakpoint(dbg, workerSource, 1);
|
||||
invokeInTab("startWorker");
|
||||
await waitForPaused(dbg, "simple-worker.js");
|
||||
|
||||
// We should be paused at the first line of simple-worker.js
|
||||
assertPausedAtSourceAndLine(dbg, workerSource.id, 1);
|
||||
await removeBreakpoint(dbg, workerSource.id, 1);
|
||||
await removeBreakpoint(dbg, workerSource.id, 1, 12);
|
||||
await resume(dbg);
|
||||
|
||||
// Make sure that suspending activity in the worker when attaching does not
|
||||
|
@ -31,5 +32,5 @@ add_task(async function() {
|
|||
|
||||
// We should be paused in the message listener in simple-worker.js
|
||||
assertPausedAtSourceAndLine(dbg, workerSource.id, 10);
|
||||
await removeBreakpoint(dbg, workerSource.id, 10);
|
||||
await removeBreakpoint(dbg, workerSource.id, 10, 2);
|
||||
});
|
||||
|
|
|
@ -90,6 +90,7 @@ add_task(async function() {
|
|||
await addBreakpoint(dbg, "simple-worker", 10);
|
||||
invokeInTab("sayHello");
|
||||
dbg.actions.selectThread(worker1Thread);
|
||||
|
||||
await waitForPaused(dbg);
|
||||
assertPausedAtSourceAndLine(dbg, workerSource.id, 10);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
// source. It also needs to introduce a new global variable so
|
||||
// it's not immediately garbage collected.
|
||||
inline_script = function () { var x = 5; };
|
||||
inline_script();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -17,6 +17,8 @@ var { Toolbox } = require("devtools/client/framework/toolbox");
|
|||
var { Task } = require("devtools/shared/task");
|
||||
var asyncStorage = require("devtools/shared/async-storage");
|
||||
|
||||
const { getSelectedLocation } = require("devtools/client/debugger/new/src/utils/source-maps");
|
||||
|
||||
const sourceUtils = {
|
||||
isLoaded: source => source.loadedState === "loaded"
|
||||
};
|
||||
|
@ -219,10 +221,17 @@ async function waitForElementWithSelector(dbg, selector) {
|
|||
}
|
||||
|
||||
function waitForSelectedSource(dbg, url) {
|
||||
const {
|
||||
getSelectedSource,
|
||||
hasSymbols,
|
||||
hasSourceMetaData,
|
||||
hasBreakpointPositions
|
||||
} = dbg.selectors;
|
||||
|
||||
return waitForState(
|
||||
dbg,
|
||||
state => {
|
||||
const source = dbg.selectors.getSelectedSource(state);
|
||||
const source = getSelectedSource(state);
|
||||
const isLoaded = source && sourceUtils.isLoaded(source);
|
||||
if (!isLoaded) {
|
||||
return false;
|
||||
|
@ -237,13 +246,9 @@ function waitForSelectedSource(dbg, url) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// wait for async work to be done
|
||||
const hasSymbols = dbg.selectors.hasSymbols(state, source);
|
||||
const hasSourceMetaData = dbg.selectors.hasSourceMetaData(
|
||||
state,
|
||||
source.id
|
||||
);
|
||||
return hasSymbols && hasSourceMetaData;
|
||||
return hasSymbols(state, source) &&
|
||||
hasSourceMetaData( state, source.id) &&
|
||||
hasBreakpointPositions(state, source.id);
|
||||
},
|
||||
"selected source"
|
||||
);
|
||||
|
@ -731,6 +736,14 @@ async function navigate(dbg, url, ...sources) {
|
|||
return waitForSources(dbg, ...sources);
|
||||
}
|
||||
|
||||
function getFirstBreakpointColumn(dbg, {line, sourceId}) {
|
||||
const {getSource, getFirstBreakpointPosition} = dbg.selectors;
|
||||
const source = getSource(dbg.getState(), sourceId)
|
||||
const position = getFirstBreakpointPosition(dbg.getState(), { line, sourceId });
|
||||
|
||||
return getSelectedLocation(position, source).column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a breakpoint to a source at line/col.
|
||||
*
|
||||
|
@ -742,11 +755,15 @@ async function navigate(dbg, url, ...sources) {
|
|||
* @return {Promise}
|
||||
* @static
|
||||
*/
|
||||
function addBreakpoint(dbg, source, line, column) {
|
||||
async function addBreakpoint(dbg, source, line, column) {
|
||||
source = findSource(dbg, source);
|
||||
const sourceId = source.id;
|
||||
column = column || getFirstBreakpointColumn(dbg, {line, sourceId: source.id});
|
||||
const bpCount = dbg.selectors.getBreakpointCount(dbg.getState());
|
||||
Cu.forceGC();
|
||||
dbg.actions.addBreakpoint({ sourceId, line, column });
|
||||
return waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||
await waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||
is(dbg.selectors.getBreakpointCount(dbg.getState()), bpCount + 1, "a new breakpoint was created");
|
||||
}
|
||||
|
||||
function disableBreakpoint(dbg, source, line, column) {
|
||||
|
@ -758,22 +775,11 @@ function disableBreakpoint(dbg, source, line, column) {
|
|||
|
||||
function findBreakpoint(dbg, url, line) {
|
||||
const {
|
||||
selectors: { getBreakpoint },
|
||||
selectors: { getBreakpoint, getBreakpointsList },
|
||||
getState
|
||||
} = dbg;
|
||||
const source = findSource(dbg, url);
|
||||
let column;
|
||||
if (
|
||||
Services.prefs.getBoolPref("devtools.debugger.features.column-breakpoints")
|
||||
) {
|
||||
({ column } = dbg.selectors.getFirstVisibleBreakpointPosition(
|
||||
dbg.store.getState(),
|
||||
{
|
||||
sourceId: source.id,
|
||||
line
|
||||
}
|
||||
));
|
||||
}
|
||||
const column = getFirstBreakpointColumn(dbg, {line, sourceId: source.id });
|
||||
return getBreakpoint(getState(), { sourceId: source.id, line, column });
|
||||
}
|
||||
|
||||
|
@ -894,6 +900,7 @@ async function assertScopes(dbg, items) {
|
|||
*/
|
||||
function removeBreakpoint(dbg, sourceId, line, column) {
|
||||
const source = dbg.selectors.getSource(dbg.getState(), sourceId);
|
||||
column = column || getFirstBreakpointColumn(dbg, {line, sourceId});
|
||||
const location = { sourceId, sourceUrl: source.url, line, column };
|
||||
const bp = dbg.selectors.getBreakpointForLocation(dbg.getState(), location);
|
||||
dbg.actions.removeBreakpoint(bp);
|
||||
|
@ -1220,8 +1227,15 @@ async function clickElement(dbg, elementName, ...args) {
|
|||
}
|
||||
|
||||
function clickElementWithSelector(dbg, selector) {
|
||||
clickDOMElement(
|
||||
dbg,
|
||||
findElementWithSelector(dbg, selector)
|
||||
);
|
||||
}
|
||||
|
||||
function clickDOMElement(dbg, element) {
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
findElementWithSelector(dbg, selector),
|
||||
element,
|
||||
{},
|
||||
dbg.win
|
||||
);
|
||||
|
@ -1318,6 +1332,33 @@ async function waitForScrolling(codeMirror) {
|
|||
});
|
||||
}
|
||||
|
||||
async function codeMirrorGutterElement(dbg, line) {
|
||||
info(`CodeMirror line ${line}`);
|
||||
const cm = getCM(dbg);
|
||||
|
||||
const position = { line: line - 1, ch: 0 };
|
||||
cm.scrollIntoView(position, 0);
|
||||
await waitForScrolling(cm);
|
||||
|
||||
const coords = getCoordsFromPosition(cm, position);
|
||||
|
||||
const { left, top } = coords;
|
||||
|
||||
// Adds a vertical offset due to increased line height
|
||||
// https://github.com/firefox-devtools/debugger/pull/7934
|
||||
const lineHeightOffset = 3;
|
||||
|
||||
const tokenEl = dbg.win.document.elementFromPoint(
|
||||
left,
|
||||
top + lineHeightOffset
|
||||
);
|
||||
|
||||
if (!tokenEl) {
|
||||
throw new Error("Failed to find element for line " + line);
|
||||
}
|
||||
return tokenEl;
|
||||
}
|
||||
|
||||
async function hoverAtPos(dbg, { line, ch }) {
|
||||
info(`Hovering at ${line}, ${ch}`);
|
||||
const cm = getCM(dbg);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* global toolbox, createDebuggerContext, waitForSources, testUrl,
|
||||
waitForPaused, addBreakpoint, assertPausedLocation, stepIn,
|
||||
findSource, removeBreakpoint, resume */
|
||||
findSource, removeBreakpoint, resume, selectSource */
|
||||
|
||||
info(`START: ${new Error().lineNumber}`);
|
||||
|
||||
|
@ -34,6 +34,7 @@ info(`START: ${new Error().lineNumber}`);
|
|||
script.click();
|
||||
|
||||
const onPaused = waitForPaused(dbg);
|
||||
await selectSource(dbg, fileName);
|
||||
await addBreakpoint(dbg, fileName, 2);
|
||||
|
||||
await onPaused;
|
||||
|
|
|
@ -7249,6 +7249,8 @@ async function getGeneratedRangesForOriginal(sourceId, url, mergeUnmappedRegions
|
|||
assert(isOriginalId(sourceId), "Source is not an original source");
|
||||
|
||||
const map = await getSourceMap(originalToGeneratedId(sourceId));
|
||||
|
||||
// NOTE: this is only needed for Flow
|
||||
if (!map) {
|
||||
return [];
|
||||
}
|
||||
|
@ -7258,9 +7260,18 @@ async function getGeneratedRangesForOriginal(sourceId, url, mergeUnmappedRegions
|
|||
map.computeColumnSpans();
|
||||
}
|
||||
|
||||
const cachedGeneratedMappingsForOriginal = GENERATED_MAPPINGS.get(map);
|
||||
if (cachedGeneratedMappingsForOriginal) {
|
||||
return cachedGeneratedMappingsForOriginal;
|
||||
if (!GENERATED_MAPPINGS.has(map)) {
|
||||
GENERATED_MAPPINGS.set(map, new Map());
|
||||
}
|
||||
|
||||
const generatedRangesMap = GENERATED_MAPPINGS.get(map);
|
||||
if (!generatedRangesMap) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (generatedRangesMap.has(sourceId)) {
|
||||
// NOTE we need to coerce the result to an array for Flow
|
||||
return generatedRangesMap.get(sourceId) || [];
|
||||
}
|
||||
|
||||
// Gather groups of mappings on the generated file, with new groups created
|
||||
|
@ -7322,7 +7333,7 @@ async function getGeneratedRangesForOriginal(sourceId, url, mergeUnmappedRegions
|
|||
}
|
||||
}
|
||||
|
||||
GENERATED_MAPPINGS.set(map, generatedMappingsForOriginal);
|
||||
generatedRangesMap.set(sourceId, generatedMappingsForOriginal);
|
||||
return generatedMappingsForOriginal;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ add_task(async function() {
|
|||
const toolbox = gDevTools.getToolbox(hud.target);
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
|
||||
await selectSource(dbg, "test-closure-optimized-out.html");
|
||||
await addBreakpoint(dbg, "test-closure-optimized-out.html", breakpointLine);
|
||||
|
||||
// Cause the debuggee to pause
|
||||
|
|
|
@ -239,8 +239,10 @@ async function addBreakpoint(dbg, line, url) {
|
|||
const location = {
|
||||
sourceId: source.id,
|
||||
line,
|
||||
column: 0,
|
||||
};
|
||||
|
||||
await selectSource(dbg, url);
|
||||
|
||||
const onDispatched = waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||
dbg.actions.addBreakpoint(location);
|
||||
return onDispatched;
|
||||
|
|
Загрузка…
Ссылка в новой задаче