Bug 1524374 - Remove breakpoint actors, r=jlast.

--HG--
extra : rebase_source : 066264dbc1f73f3afb403a9c04f5b5dbd7d53613
This commit is contained in:
Brian Hackett 2019-02-06 09:18:33 -10:00
Родитель ffb2a3ad9f
Коммит 56d2836638
64 изменённых файлов: 567 добавлений и 1179 удалений

Просмотреть файл

@ -11,7 +11,7 @@ import {
getASTLocation,
assertLocation,
makeBreakpointId,
makeSourceActorLocation
makeBreakpointLocation
} from "../../utils/breakpoint";
import { PROMISE } from "../utils/middleware/promise";
import {
@ -71,15 +71,8 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
return newBreakpoint;
}
const sourceActors = getSourceActors(state, generatedSource.id);
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
generatedLocation
);
await client.setBreakpoint(sourceActorLocation, breakpoint.options);
}
const breakpointLocation = makeBreakpointLocation(getState(), generatedLocation);
await client.setBreakpoint(breakpointLocation, breakpoint.options);
const symbols = getSymbols(getState(), source);
const astLocation = await getASTLocation(source, symbols, location);

Просмотреть файл

@ -23,7 +23,7 @@ import {
import {
assertBreakpoint,
createXHRBreakpoint,
makeSourceActorLocation
makeBreakpointLocation
} from "../../utils/breakpoint";
import {
addBreakpoint,
@ -49,19 +49,8 @@ import type {
import { recordEvent } from "../../utils/telemetry";
async function removeBreakpointsPromise(client, state, breakpoint) {
const sourceActors = getSourceActors(
state,
breakpoint.generatedLocation.sourceId
);
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
breakpoint.generatedLocation
);
if (client.getBreakpointByLocation(sourceActorLocation)) {
await client.removeBreakpoint(sourceActorLocation);
}
}
const breakpointLocation = makeBreakpointLocation(state, breakpoint.generatedLocation);
await client.removeBreakpoint(breakpointLocation);
}
/**
@ -304,19 +293,8 @@ export function setBreakpointOptions(
await dispatch(enableBreakpoint(bp));
}
const sourceActors = getSourceActors(
getState(),
bp.generatedLocation.sourceId
);
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
bp.generatedLocation
);
if (client.getBreakpointByLocation(sourceActorLocation)) {
await client.setBreakpointOptions(sourceActorLocation, options);
}
}
const breakpointLocation = makeBreakpointLocation(getState(), bp.generatedLocation);
await client.setBreakpoint(breakpointLocation, options);
const newBreakpoint = { ...bp, disabled: false, options };

Просмотреть файл

@ -11,7 +11,8 @@ import {
assertBreakpoint,
assertPendingBreakpoint,
findScopeByName,
makeSourceActorLocation
makeSourceActorLocation,
makeBreakpointLocation
} from "../../utils/breakpoint";
import { getGeneratedLocation } from "../../utils/source-maps";
@ -125,7 +126,16 @@ export async function syncBreakpointPromise(
scopedGeneratedLocation
);
const sourceActors = getSourceActors(getState(), sourceId);
// 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 scopedBreakpointLocation =
makeBreakpointLocation(getState(), scopedGeneratedLocation);
let possiblePosition = true;
if (features.columnBreakpoints && generatedLocation.column != undefined) {
const { positions } = await dispatch(
@ -141,19 +151,7 @@ export async function syncBreakpointPromise(
if (possiblePosition && (pendingBreakpoint.disabled || isSameLocation)) {
// Make sure the breakpoint is installed on all source actors.
if (!pendingBreakpoint.disabled) {
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
generatedLocation
);
if (!client.getBreakpointByLocation(sourceActorLocation)) {
await client.setBreakpoint(
sourceActorLocation,
pendingBreakpoint.options,
isOriginalId(sourceId)
);
}
}
await client.setBreakpoint(breakpointLocation, pendingBreakpoint.options);
}
const originalText = getTextAtPosition(source, previousLocation);
@ -170,15 +168,7 @@ export async function syncBreakpointPromise(
}
// clear server breakpoints if they exist and we have moved
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
generatedLocation
);
if (client.getBreakpointByLocation(sourceActorLocation)) {
await client.removeBreakpoint(sourceActorLocation);
}
}
await client.removeBreakpoint(breakpointLocation);
if (!possiblePosition || !scopedGeneratedLocation.line) {
return { previousLocation, breakpoint: null };
@ -188,18 +178,12 @@ 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.
for (const sourceActor of sourceActors) {
const sourceActorLocation = makeSourceActorLocation(
sourceActor,
scopedGeneratedLocation
);
await client.setBreakpoint(
sourceActorLocation,
pendingBreakpoint.options,
isOriginalId(sourceId)
);
if (!scopedGeneratedLocation.line) {
return { previousLocation, breakpoint: null };
}
await client.setBreakpoint(scopedGeneratedLocation, pendingBreakpoint.options);
const originalText = getTextAtPosition(source, scopedLocation);
const text = getTextAtPosition(generatedSource, scopedGeneratedLocation);

Просмотреть файл

@ -42,6 +42,7 @@ import {
selectors,
actions,
makeOriginalSource,
makeSource,
waitForState
} from "../../utils/test-head";
@ -128,6 +129,8 @@ describe("when adding breakpoints", () => {
loadInitialState()
);
await dispatch(actions.newSource(makeSource("foo")));
const csr1 = makeOriginalSource("foo");
const csr2 = makeOriginalSource("foo2");
@ -178,6 +181,8 @@ describe("when changing an existing breakpoint", () => {
const bp = generateBreakpoint("foo");
const id = makePendingLocationId(bp.location);
await dispatch(actions.newSource(makeSource("foo")));
const csr = makeOriginalSource("foo");
await dispatch(actions.newSource(csr));
await dispatch(actions.loadSourceText(csr.source));
@ -229,6 +234,8 @@ describe("initializing when pending breakpoints exist in prefs", () => {
);
const bar = generateBreakpoint("bar.js");
await dispatch(actions.newSource(makeSource("bar.js")));
const csr = makeOriginalSource("bar.js");
await dispatch(actions.newSource(csr));
await dispatch(actions.loadSourceText(csr.source));
@ -267,6 +274,7 @@ describe("initializing with disabled pending breakpoints in prefs", () => {
const { getState, dispatch } = store;
const csr = makeOriginalSource("bar.js");
await dispatch(actions.newSource(makeSource("bar.js")));
await dispatch(actions.newSource(csr));
await dispatch(actions.loadSourceText(csr.source));
@ -297,6 +305,8 @@ describe("adding sources", () => {
expect(selectors.getBreakpointCount(getState())).toEqual(0);
const csr = makeOriginalSource("bar.js");
await dispatch(actions.newSource(makeSource("bar.js")));
await dispatch(actions.newSource(csr));
await dispatch(actions.loadSourceText(csr.source));
@ -322,6 +332,7 @@ describe("adding sources", () => {
expect(selectors.getBreakpointCount(getState())).toEqual(0);
await dispatch(actions.newSource(makeSource("bar.js")));
await dispatch(actions.newSource(csr));
await waitForState(store, state => selectors.getBreakpointCount(state) > 0);
@ -337,12 +348,15 @@ describe("adding sources", () => {
const csr1 = makeOriginalSource("bar.js");
const csr2 = makeOriginalSource("foo.js");
await dispatch(actions.newSource(makeSource("bar.js")));
await dispatch(actions.newSources([csr1, csr2]));
await dispatch(actions.loadSourceText(csr1.source));
await dispatch(actions.loadSourceText(csr2.source));
await waitForState(store, state => selectors.getBreakpointCount(state) > 0);
expect(selectors.getBreakpointCount(getState())).toEqual(1);
// N.B. this test is kind of broken and creates different breakpoints for
// the generated and original bar.js sources.
expect(selectors.getBreakpointCount(getState())).toEqual(2);
});
});

Просмотреть файл

@ -14,7 +14,7 @@ function createObjectClient(grip: Grip) {
return DebuggerClient.createObjectClient(grip);
}
export async function onConnect(connection: any, actions: Object): Object {
export async function onConnect(connection: any, actions: Object) {
const {
tabConnection: { tabTarget, threadClient, debuggerClient }
} = connection;
@ -22,13 +22,13 @@ export async function onConnect(connection: any, actions: Object): Object {
DebuggerClient = debuggerClient;
if (!tabTarget || !threadClient || !debuggerClient) {
return { bpClients: {} };
return;
}
const supportsWasm =
features.wasm && !!debuggerClient.mainRoot.traits.wasmBinarySource;
const { bpClients } = setupCommands({
setupCommands({
threadClient,
tabTarget,
debuggerClient,
@ -69,8 +69,6 @@ export async function onConnect(connection: any, actions: Object): Object {
if (pausedPacket) {
clientEvents.paused(threadClient, "paused", pausedPacket);
}
return { bpClients };
}
export { createObjectClient, clientCommands, clientEvents };

Просмотреть файл

@ -6,6 +6,7 @@
import type {
ActorId,
BreakpointLocation,
BreakpointOptions,
BreakpointResult,
EventListenerBreakpoints,
@ -24,7 +25,6 @@ import type {
Grip,
ThreadClient,
ObjectClient,
BPClients,
SourcesPacket
} from "./types";
@ -37,12 +37,12 @@ import { supportsWorkers, updateWorkerClients } from "./workers";
import { features } from "../../utils/prefs";
let bpClients: BPClients;
let workerClients: Object;
let threadClient: ThreadClient;
let tabTarget: TabTarget;
let debuggerClient: DebuggerClient;
let sourceActors: { [ActorId]: SourceId };
let breakpoints: { [string]: Object };
let supportsWasm: boolean;
type Dependencies = {
@ -52,16 +52,14 @@ type Dependencies = {
supportsWasm: boolean
};
function setupCommands(dependencies: Dependencies): { bpClients: BPClients } {
function setupCommands(dependencies: Dependencies) {
threadClient = dependencies.threadClient;
tabTarget = dependencies.tabTarget;
debuggerClient = dependencies.debuggerClient;
supportsWasm = dependencies.supportsWasm;
bpClients = {};
workerClients = {};
sourceActors = {};
return { bpClients };
breakpoints = {};
}
function createObjectClient(grip: Grip) {
@ -159,26 +157,6 @@ async function sourceContents({
return { source, contentType };
}
function getBreakpointByLocation(location: SourceActorLocation) {
const id = makeBreakpointActorId(location);
const bpClient = bpClients[id];
if (bpClient) {
const { actor, url, line, column } = bpClient.location;
return {
id: bpClient.actor,
options: bpClient.options,
actualLocation: {
line,
column,
sourceId: actor,
sourceUrl: url
}
};
}
return null;
}
function setXHRBreakpoint(path: string, method: string) {
return threadClient.setXHRBreakpoint(path, method);
}
@ -187,61 +165,34 @@ function removeXHRBreakpoint(path: string, method: string) {
return threadClient.removeXHRBreakpoint(path, method);
}
function setBreakpoint(
location: SourceActorLocation,
options: BreakpointOptions
) {
const sourceThreadClient = lookupThreadClient(location.sourceActor.thread);
const sourceClient = sourceThreadClient.source({
actor: location.sourceActor.actor
});
return sourceClient
.setBreakpoint({
line: location.line,
column: location.column,
options,
})
.then(([, bpClient]) => {
const id = makeBreakpointActorId(location);
bpClients[id] = bpClient;
});
// 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 removeBreakpoint(
location: SourceActorLocation
): Promise<void> | ?BreakpointResult {
try {
const id = makeBreakpointActorId(location);
const bpClient = bpClients[id];
if (!bpClient) {
console.warn("No breakpoint to delete on server");
return Promise.resolve();
}
delete bpClients[id];
return bpClient.remove();
} catch (_error) {
console.warn("No breakpoint to delete on server");
function* getAllThreadClients() {
yield threadClient;
for (const { thread } of (Object.values(workerClients): any)) {
yield thread;
}
}
function setBreakpointOptions(
location: SourceActorLocation,
async function setBreakpoint(
location: BreakpointLocation,
options: BreakpointOptions
) {
const id = makeBreakpointActorId(location);
const bpClient = bpClients[id];
breakpoints[locationKey(location)] = { location, options };
for (const thread of getAllThreadClients()) {
await thread.setBreakpoint(location, options);
}
}
if (debuggerClient.mainRoot.traits.nativeLogpoints) {
bpClient.setOptions(options);
} else {
// Older server breakpoints destroy themselves when changing options.
delete bpClients[id];
bpClient
.setOptions(options)
.then(_bpClient => {
bpClients[id] = _bpClient;
});
async function removeBreakpoint(location: BreakpointLocation) {
delete breakpoints[locationKey(location)];
for (const thread of getAllThreadClients()) {
await thread.removeBreakpoint(location);
}
}
@ -418,18 +369,26 @@ function getSourceForActor(actor: ActorId) {
async function fetchWorkers(): Promise<Worker[]> {
if (features.windowlessWorkers) {
workerClients = await updateWorkerClients({
const newWorkerClients = await updateWorkerClients({
tabTarget,
debuggerClient,
threadClient,
workerClients
});
const workerNames = Object.getOwnPropertyNames(workerClients);
// Fetch the sources and install breakpoints on any new workers.
const workerNames = Object.getOwnPropertyNames(newWorkerClients);
for (const actor of workerNames) {
if (!workerClients[actor]) {
const client = newWorkerClients[actor].thread;
createSources(client);
for (const { location, options } of (Object.values(breakpoints): any)) {
client.setBreakpoint(location, options);
}
}
}
workerNames.forEach(actor => {
createSources(workerClients[actor].thread);
});
workerClients = newWorkerClients;
return workerNames.map(actor =>
createWorker(actor, workerClients[actor].url)
@ -484,13 +443,11 @@ const clientCommands = {
breakOnNext,
sourceContents,
getSourceForActor,
getBreakpointByLocation,
getBreakpointPositions,
setBreakpoint,
setXHRBreakpoint,
removeXHRBreakpoint,
removeBreakpoint,
setBreakpointOptions,
evaluate,
evaluateInFrame,
evaluateExpressions,

Просмотреть файл

@ -11,6 +11,7 @@
*/
import type {
BreakpointLocation,
BreakpointOptions,
FrameId,
ActorId,
@ -327,11 +328,6 @@ export type SourceClient = {
source: () => { source: any, contentType?: string },
_activeThread: ThreadClient,
actor: string,
setBreakpoint: ({
line: number,
column: ?number,
condition: ?string
}) => Promise<BreakpointResponse>,
getBreakpointPositionsCompressed: (range: {
start: { line: number },
end: { line: number }
@ -370,6 +366,8 @@ export type ThreadClient = {
source: ({ actor: SourceId }) => SourceClient,
pauseGrip: (Grip | Function) => ObjectClient,
pauseOnExceptions: (boolean, boolean) => Promise<*>,
setBreakpoint: (BreakpointLocation, BreakpointOptions) => Promise<*>,
removeBreakpoint: (BreakpointLocation) => Promise<*>,
setXHRBreakpoint: (path: string, method: string) => Promise<boolean>,
removeXHRBreakpoint: (path: string, method: string) => Promise<boolean>,
interrupt: () => Promise<*>,
@ -387,38 +385,6 @@ export type ThreadClient = {
setEventListenerBreakpoints: (string[]) => void
};
/**
* BreakpointClient
* @memberof firefox
* @static
*/
export type BreakpointClient = {
actor: ActorId,
remove: () => void,
location: {
actor: string,
url: string,
line: number,
column: ?number
},
setOptions: BreakpointOptions => Promise<BreakpointClient>,
// request: any,
source: SourceClient,
options: BreakpointOptions
};
export type BPClients = { [id: ActorId]: BreakpointClient };
export type BreakpointResponse = [
{
actor?: ActorId,
from?: ActorId,
isPending?: boolean,
actualLocation?: ActualLocation
},
BreakpointClient
];
export type FirefoxClientConnection = {
getTabTarget: () => TabTarget,
getThreadClient: () => ThreadClient,

Просмотреть файл

@ -29,6 +29,16 @@ function loadFromPrefs(actions: Object) {
}
}
async function syncBreakpoints() {
const breakpoints = await asyncStore.pendingBreakpoints;
const breakpointValues = (Object.values(breakpoints): any);
breakpointValues.forEach(({ disabled, options, generatedLocation }) => {
if (!disabled) {
firefox.clientCommands.setBreakpoint(generatedLocation, options);
}
});
}
function syncXHRBreakpoints() {
asyncStore.xhrBreakpoints.then(bps => {
bps.forEach(({ path, method, disabled }) => {
@ -83,6 +93,7 @@ export async function onConnect(
await client.onConnect(connection, actions);
await loadFromPrefs(actions);
syncBreakpoints();
syncXHRBreakpoints();
setupHelper({
store,

Просмотреть файл

@ -90,6 +90,17 @@ export type PendingLocation = {
+sourceUrl?: string
};
// Type of location used when setting breakpoints in the server. Exactly one of
// { sourceUrl, sourceId } must be specified. Soon this will replace
// SourceLocation and PendingLocation, and SourceActorLocation will be removed
// (bug 1524374).
export type BreakpointLocation = {
+line: number,
+column?: number,
+sourceUrl?: string,
+sourceId?: SourceId
};
export type ASTLocation = {|
+name: ?string,
+offset: PartialPosition,

Просмотреть файл

@ -6,7 +6,7 @@
import { sortBy } from "lodash";
import { getBreakpoint } from "../../selectors";
import { getBreakpoint, getSource, getSourceActors } from "../../selectors";
import { isGenerated } from "../source";
import assert from "../assert";
@ -22,6 +22,7 @@ import type {
SourceActorLocation,
PendingLocation,
Breakpoint,
BreakpointLocation,
PendingBreakpoint
} from "../../types";
@ -68,6 +69,24 @@ export function makePendingLocationId(location: SourceLocation) {
return `${sourceUrlString}:${line}:${columnString}`;
}
export function makeBreakpointLocation(state: State, location: SourceLocation): BreakpointLocation {
const source = getSource(state, location.sourceId);
if (!source) {
throw new Error("no source");
}
const breakpointLocation: any = {
line: location.line,
column: location.column
};
if (source.url) {
breakpointLocation.sourceUrl = source.url;
} else {
const sourceActors = getSourceActors(state, location.sourceId);
breakpointLocation.sourceId = sourceActors[0].actor;
}
return breakpointLocation;
}
export function makeSourceActorLocation(
sourceActor: SourceActor,
location: SourceLocation

Просмотреть файл

@ -35,7 +35,12 @@ add_task(async function() {
openFirstBreakpointContextMenu(dbg);
// select "Disable Others"
let dispatched = waitForDispatch(dbg, "DISABLE_BREAKPOINT", 3);
// FIXME bug 1524374 this waitForDispatch call only sees one dispatch for
// DISABLE_BREAKPOINT even though three are triggered, due to the order in
// which promises get resolved. The problem seems to indicate a coverage gap
// in waitUntilService(). Workaround this by only waiting for one dispatch,
// though this is fragile and could break again in the future.
let dispatched = waitForDispatch(dbg, "DISABLE_BREAKPOINT", /*3*/ 1);
selectContextMenuItem(dbg, selectors.breakpointContextMenu.disableOthers);
await waitForState(dbg, state =>
dbg.selectors.getBreakpointsList(state)

Просмотреть файл

@ -4,6 +4,13 @@
// Tests the breakpoint gutter and making sure breakpoint icons exist
// correctly
// FIXME bug 1524374 removing breakpoints in this test can cause uncaught
// rejections and make bug 1512742 permafail.
const { PromiseTestUtils } = scopedCuImport(
"resource://testing-common/PromiseTestUtils.jsm"
);
PromiseTestUtils.whitelistRejectionsGlobally(/NS_ERROR_NOT_INITIALIZED/);
// Utilities for interacting with the editor
function clickGutter(dbg, line) {
clickElement(dbg, "gutter", line);

Просмотреть файл

@ -8,9 +8,6 @@
"use strict";
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { breakpointSpec } = require("devtools/shared/specs/breakpoint");
/**
* Set breakpoints on all the given entry points with the given
* BreakpointActor as the handler.
@ -29,31 +26,22 @@ function setBreakpointAtEntryPoints(actor, entryPoints) {
exports.setBreakpointAtEntryPoints = setBreakpointAtEntryPoints;
/**
* BreakpointActors exist for the lifetime of their containing thread and are
* responsible for deleting breakpoints, handling breakpoint hits and
* associating breakpoints with scripts.
* BreakpointActors are instantiated for each breakpoint that has been installed
* by the client. They are not true actors and do not communicate with the
* client directly, but encapsulate the DebuggerScript locations where the
* breakpoint is installed.
*/
const BreakpointActor = ActorClassWithSpec(breakpointSpec, {
/**
* Create a Breakpoint actor.
*
* @param ThreadActor threadActor
* The parent thread actor that contains this breakpoint.
* @param GeneratedLocation generatedLocation
* The generated location of the breakpoint.
*/
initialize: function(threadActor, generatedLocation) {
// A map from Debugger.Script instances to the offsets which the breakpoint
// has been set for in that script.
this.scripts = new Map();
function BreakpointActor(threadActor, location) {
// A map from Debugger.Script instances to the offsets which the breakpoint
// has been set for in that script.
this.scripts = new Map();
this.threadActor = threadActor;
this.generatedLocation = generatedLocation;
this.options = null;
this.isPending = true;
},
this.threadActor = threadActor;
this.location = location;
this.options = null;
}
// Called when new breakpoint options are received from the client.
BreakpointActor.prototype = {
setOptions(options) {
for (const [script, offsets] of this.scripts) {
this._updateOptionsForScript(script, offsets, this.options, options);
@ -85,7 +73,6 @@ const BreakpointActor = ActorClassWithSpec(breakpointSpec, {
script.setBreakpoint(offset, this);
}
this.isPending = false;
this._updateOptionsForScript(script, offsets, null, this.options);
},
@ -241,18 +228,13 @@ const BreakpointActor = ActorClassWithSpec(breakpointSpec, {
return this.threadActor._pauseAndRespond(frame, reason);
},
/**
* Handle a protocol request to remove this breakpoint.
*/
delete: function() {
// Remove from the breakpoint store.
if (this.generatedLocation) {
this.threadActor.breakpointActorMap.deleteActor(this.generatedLocation);
}
this.threadActor.breakpointActorMap.deleteActor(this.location);
this.threadActor.threadLifetimePool.removeActor(this);
// Remove the actual breakpoint from the associated scripts.
this.removeScripts();
},
});
};
exports.BreakpointActor = BreakpointActor;

Просмотреть файл

@ -7,8 +7,7 @@
"use strict";
const { Ci } = require("chrome");
const { BreakpointActor, setBreakpointAtEntryPoints } = require("devtools/server/actors/breakpoint");
const { GeneratedLocation } = require("devtools/server/actors/common");
const { setBreakpointAtEntryPoints } = require("devtools/server/actors/breakpoint");
const { createValueGrip } = require("devtools/server/actors/object/utils");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
@ -461,61 +460,6 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
this.pausePoints = uncompressed;
},
/**
* Handle a request to set a breakpoint.
*
* @param Number line
* Line to break on.
* @param Number column
* Column to break on.
* @param Object options
* Any options for the breakpoint.
*
* @returns Promise
* A promise that resolves to a JSON object representing the
* response.
*/
setBreakpoint: function(line, column, options) {
const location = new GeneratedLocation(this, line, column);
const actor = this._getOrCreateBreakpointActor(
location,
options
);
return {
actor: actor.actorID,
isPending: actor.isPending,
};
},
/**
* Get or create a BreakpointActor for the given location in the generated
* source, and ensure it is set as a breakpoint handler on all scripts that
* match the given location.
*
* @param GeneratedLocation generatedLocation
* A GeneratedLocation representing the location of the breakpoint in
* the generated source.
* @param Object options
* Any options for the breakpoint.
*
* @returns BreakpointActor
* A BreakpointActor representing the breakpoint.
*/
_getOrCreateBreakpointActor: function(generatedLocation, options) {
let actor = this.breakpointActorMap.getActor(generatedLocation);
if (!actor) {
actor = new BreakpointActor(this.threadActor, generatedLocation);
this.threadActor.threadLifetimePool.addActor(actor);
this.breakpointActorMap.setActor(generatedLocation, actor);
}
actor.setOptions(options);
this._setBreakpoint(actor);
return actor;
},
/*
* Ensure the given BreakpointActor is set as a breakpoint handler on all
* scripts that match its location in the generated source.
@ -525,31 +469,21 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
*
* @returns A Promise that resolves to the given BreakpointActor.
*/
_setBreakpoint: function(actor) {
const { generatedLocation } = actor;
const {
generatedSourceActor,
generatedLine,
generatedColumn,
generatedLastColumn,
} = generatedLocation;
applyBreakpoint: function(actor) {
const { line, column } = actor.location;
// Find all scripts that match the given source actor and line
// number.
let scripts = generatedSourceActor._findDebuggeeScripts(
{ line: generatedLine }
);
let scripts = this._findDebuggeeScripts({ line });
scripts = scripts.filter((script) => !actor.hasScript(script));
// Find all entry points that correspond to the given location.
const entryPoints = [];
if (generatedColumn === undefined) {
if (column === undefined) {
// This is a line breakpoint, so we are interested in all offsets
// that correspond to the given line number.
for (const script of scripts) {
const offsets = script.getLineOffsets(generatedLine);
const offsets = script.getLineOffsets(line);
if (offsets.length > 0) {
entryPoints.push({ script, offsets });
}
@ -561,15 +495,15 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
[
script,
script.getAllColumnOffsets()
.filter(({ lineNumber }) => lineNumber === generatedLine),
.filter(({ lineNumber }) => lineNumber === line),
]
);
// This is a column breakpoint, so we are interested in all column
// offsets that correspond to the given line *and* column number.
for (const [script, columnToOffsetMap] of columnToOffsetMaps) {
for (const { columnNumber: column, offset } of columnToOffsetMap) {
if (column >= generatedColumn && column <= generatedLastColumn) {
for (const { columnNumber, offset } of columnToOffsetMap) {
if (columnNumber >= column && columnNumber <= column + 1) {
entryPoints.push({ script, offsets: [offset] });
}
}
@ -584,8 +518,8 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
// of caution by handling it here.
const closestScripts = findClosestScriptBySource(
columnToOffsetMaps.map(pair => pair[0]),
generatedLine,
generatedColumn,
line,
column,
);
const columnToOffsetLookup = new Map(columnToOffsetMaps);
@ -596,11 +530,11 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
const firstColumnOffset = columnToOffsetMap[0];
const lastColumnOffset = columnToOffsetMap[columnToOffsetMap.length - 1];
if (generatedColumn < firstColumnOffset.columnNumber) {
if (column < firstColumnOffset.columnNumber) {
entryPoints.push({ script, offsets: [firstColumnOffset.offset] });
}
if (generatedColumn > lastColumnOffset.columnNumber) {
if (column > lastColumnOffset.columnNumber) {
entryPoints.push({ script, offsets: [lastColumnOffset.offset] });
}
}

Просмотреть файл

@ -18,7 +18,6 @@ const { threadSpec } = require("devtools/shared/specs/script");
loader.lazyRequireGetter(this, "findCssSelector", "devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "EnvironmentActor", "devtools/server/actors/environment", true);
loader.lazyRequireGetter(this, "SourceActorStore", "devtools/server/actors/utils/source-actor-store", true);
loader.lazyRequireGetter(this, "BreakpointActorMap", "devtools/server/actors/utils/breakpoint-actor-map", true);
loader.lazyRequireGetter(this, "PauseScopedObjectActor", "devtools/server/actors/pause-scoped", true);
loader.lazyRequireGetter(this, "EventLoopStack", "devtools/server/actors/utils/event-loop", true);
@ -66,8 +65,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
autoBlackBox: false,
};
this.breakpointActorMap = new BreakpointActorMap();
this.sourceActorStore = new SourceActorStore();
this.breakpointActorMap = new BreakpointActorMap(this);
this._debuggerSourcesSeen = null;
@ -152,6 +150,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return this._parent.sources;
},
get breakpoints() {
return this._parent.breakpoints;
},
get youngestFrame() {
if (this.state != "paused") {
return null;
@ -209,11 +211,6 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this.onResume();
}
// Blow away our source actor ID store because those IDs are only
// valid for this connection. This is ok because we never keep
// things like breakpoints across connections.
this._sourceActorStore = null;
this._xhrBreakpoints = [];
this._updateNetworkObserver();
@ -316,6 +313,24 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
({ path, method }) => path === p && method === m);
},
setBreakpoint(location, options) {
const actor = this.breakpointActorMap.getOrCreateBreakpointActor(location);
actor.setOptions(options);
const sourceActor = location.sourceUrl
? this.sources.getSourceActorByURL(location.sourceUrl)
: this.sources.getSourceActorById(location.sourceId);
if (sourceActor) {
sourceActor.applyBreakpoint(actor);
}
},
removeBreakpoint(location) {
const actor = this.breakpointActorMap.getOrCreateBreakpointActor(location);
actor.delete();
},
removeXHRBreakpoint: function(path, method) {
const index = this._findXHRBreakpointIndex(path, method);
@ -1786,30 +1801,17 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
sourceActor = this.sources.createSourceActor(source);
}
const bpActors = [...this.breakpointActorMap.findActors()]
.filter((actor) => {
const bpSource = actor.generatedLocation.generatedSourceActor;
return bpSource.source ? bpSource.source === source : bpSource.url === source.url;
});
// Bug 1225160: If addSource is called in response to a new script
// notification, and this notification was triggered by loading a JSM from
// chrome code, calling unsafeSynchronize could cause a debuggee timer to
// fire. If this causes the JSM to be loaded a second time, the browser
// will crash, because loading JSMS is not reentrant, and the first load
// has not completed yet.
//
// The root of the problem is that unsafeSynchronize can cause debuggee
// code to run. Unfortunately, fixing that is prohibitively difficult. The
// best we can do at the moment is disable source maps for the browser
// debugger, and carefully avoid the use of unsafeSynchronize in this
// function when source maps are disabled.
for (const actor of bpActors) {
actor.generatedLocation.generatedSourceActor._setBreakpoint(actor);
if (this._onLoadBreakpointURLs.has(source.url)) {
this.setBreakpoint({ sourceUrl: source.url, line: 1 }, {});
}
if (this._onLoadBreakpointURLs.has(source.url)) {
sourceActor.setBreakpoint(1);
const bpActors = this.breakpointActorMap.findActors()
.filter((actor) => {
return actor.location.sourceUrl && actor.location.sourceUrl == source.url;
});
for (const actor of bpActors) {
sourceActor.applyBreakpoint(actor);
}
this._debuggerSourcesSeen.add(source);

Просмотреть файл

@ -117,14 +117,7 @@ TabSources.prototype = {
contentType: contentType,
});
const sourceActorStore = this._thread.sourceActorStore;
const id = sourceActorStore.getReusableActorId(source, originalUrl);
if (id) {
actor.actorID = id;
}
this._thread.threadLifetimePool.addActor(actor);
sourceActorStore.setReusableActorId(source, originalUrl, actor.actorID);
if (this._autoBlackBox &&
!this.neverAutoBlackBoxSources.has(actor.url) &&
@ -182,8 +175,16 @@ TabSources.prototype = {
return this._htmlDocumentSourceActors[url];
}
}
return null;
},
throw new Error("getSourceActorByURL: could not find source for " + url);
getSourceActorById(actorId) {
for (const [, actor] of this._sourceActors) {
if (actor.actorID == actorId) {
return actor;
}
}
return null;
},
/**

Просмотреть файл

@ -6,169 +6,59 @@
"use strict";
const { GeneratedLocation } = require("devtools/server/actors/common");
const { BreakpointActor } = require("devtools/server/actors/breakpoint");
/**
* A BreakpointActorMap is a map from locations to instances of BreakpointActor.
*/
function BreakpointActorMap() {
this._size = 0;
function BreakpointActorMap(threadActor) {
this._threadActor = threadActor;
this._actors = {};
}
BreakpointActorMap.prototype = {
/**
* Return the number of BreakpointActors in this BreakpointActorMap.
*
* @returns Number
* The number of BreakpointActor in this BreakpointActorMap.
*/
get size() {
return this._size;
// Get the key in the _actors table for a given breakpoint location.
// See also duplicate code in commands.js :(
_locationKey(location) {
const { sourceUrl, sourceId, line, column } = location;
return `${sourceUrl}:${sourceId}:${line}:${column}`;
},
/**
* Generate all BreakpointActors that match the given location in
* this BreakpointActorMap.
*
* @param GeneratedLocation location
* The location for which matching BreakpointActors should be generated.
* Return all BreakpointActors in this BreakpointActorMap.
*/
findActors: function* (location = new GeneratedLocation()) {
// Fast shortcut for when we know we won't find any actors. Surprisingly
// enough, this speeds up refreshing when there are no breakpoints set by
// about 2x!
if (this.size === 0) {
return;
}
function* findKeys(obj, key) {
if (key !== undefined) {
if (key in obj) {
yield key;
}
} else {
for (key of Object.keys(obj)) {
yield key;
}
}
}
const query = {
sourceActorID: location.generatedSourceActor
? location.generatedSourceActor.actorID
: undefined,
line: location.generatedLine,
};
// If location contains a line, assume we are searching for a whole line
// breakpoint, and set begin/endColumn accordingly. Otherwise, we are
// searching for all breakpoints, so begin/endColumn should be left unset.
if (location.generatedLine) {
query.beginColumn = location.generatedColumn ? location.generatedColumn : 0;
query.endColumn = location.generatedColumn
? location.generatedColumn + 1
: Infinity;
} else {
query.beginColumn = location.generatedColumn ? query.generatedColumn : undefined;
query.endColumn = location.generatedColumn ? query.generatedColumn + 1 : undefined;
}
for (const sourceActorID of findKeys(this._actors, query.sourceActorID)) {
const actor = this._actors[sourceActorID];
for (const line of findKeys(actor, query.line)) {
for (const beginColumn of findKeys(actor[line], query.beginColumn)) {
for (const endColumn of findKeys(actor[line][beginColumn],
query.endColumn)) {
yield actor[line][beginColumn][endColumn];
}
}
}
}
findActors() {
return Object.values(this._actors);
},
/**
* Return the BreakpointActor at the given location in this
* BreakpointActorMap.
*
* @param GeneratedLocation location
* @param BreakpointLocation location
* The location for which the BreakpointActor should be returned.
*
* @returns BreakpointActor actor
* The BreakpointActor at the given location.
*/
getActor: function(generatedLocation) {
for (const actor of this.findActors(generatedLocation)) {
return actor;
getOrCreateBreakpointActor(location) {
const key = this._locationKey(location);
if (!this._actors[key]) {
this._actors[key] = new BreakpointActor(this._threadActor, location);
}
return null;
},
/**
* Set the given BreakpointActor to the given location in this
* BreakpointActorMap.
*
* @param GeneratedLocation location
* The location to which the given BreakpointActor should be set.
*
* @param BreakpointActor actor
* The BreakpointActor to be set to the given location.
*/
setActor: function(location, actor) {
const { generatedSourceActor, generatedLine, generatedColumn } = location;
const sourceActorID = generatedSourceActor.actorID;
const line = generatedLine;
const beginColumn = generatedColumn ? generatedColumn : 0;
const endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (!this._actors[sourceActorID]) {
this._actors[sourceActorID] = [];
}
if (!this._actors[sourceActorID][line]) {
this._actors[sourceActorID][line] = [];
}
if (!this._actors[sourceActorID][line][beginColumn]) {
this._actors[sourceActorID][line][beginColumn] = [];
}
if (!this._actors[sourceActorID][line][beginColumn][endColumn]) {
++this._size;
}
this._actors[sourceActorID][line][beginColumn][endColumn] = actor;
return this._actors[key];
},
/**
* Delete the BreakpointActor from the given location in this
* BreakpointActorMap.
*
* @param GeneratedLocation location
* @param BreakpointLocation location
* The location from which the BreakpointActor should be deleted.
*/
deleteActor: function(location) {
const { generatedSourceActor, generatedLine, generatedColumn } = location;
const sourceActorID = generatedSourceActor.actorID;
const line = generatedLine;
const beginColumn = generatedColumn ? generatedColumn : 0;
const endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (this._actors[sourceActorID]) {
if (this._actors[sourceActorID][line]) {
if (this._actors[sourceActorID][line][beginColumn]) {
if (this._actors[sourceActorID][line][beginColumn][endColumn]) {
--this._size;
}
delete this._actors[sourceActorID][line][beginColumn][endColumn];
if (Object.keys(this._actors[sourceActorID][line][beginColumn]).length === 0) {
delete this._actors[sourceActorID][line][beginColumn];
}
}
if (Object.keys(this._actors[sourceActorID][line]).length === 0) {
delete this._actors[sourceActorID][line];
}
}
}
deleteActor(location) {
const key = this._locationKey(location);
delete this._actors[key];
},
};

Просмотреть файл

@ -19,7 +19,6 @@ DevToolsModules(
'function-call.js',
'make-debugger.js',
'shapes-utils.js',
'source-actor-store.js',
'stack.js',
'TabSources.js',
'track-change-emitter.js',

Просмотреть файл

@ -1,57 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
loader.lazyRequireGetter(this, "getSourceURL", "devtools/server/actors/source", true);
/**
* Keeps track of persistent sources across reloads and ties different
* source instances to the same actor id so that things like
* breakpoints survive reloads. ThreadSources uses this to force the
* same actorID on a SourceActor.
*/
function SourceActorStore() {
// source identifier --> actor id
this._sourceActorIds = Object.create(null);
}
SourceActorStore.prototype = {
/**
* Lookup an existing actor id that represents this source, if available.
*/
getReusableActorId: function(source, originalUrl) {
const url = this.getUniqueKey(source, originalUrl);
if (url && url in this._sourceActorIds) {
return this._sourceActorIds[url];
}
return null;
},
/**
* Update a source with an actorID.
*/
setReusableActorId: function(source, originalUrl, actorID) {
const url = this.getUniqueKey(source, originalUrl);
if (url) {
this._sourceActorIds[url] = actorID;
}
},
/**
* Make a unique URL from a source that identifies it across reloads.
*/
getUniqueKey: function(source, originalUrl) {
if (originalUrl) {
// Original source from a sourcemap.
return originalUrl;
}
return getSourceURL(source);
},
};
exports.SourceActorStore = SourceActorStore;

Просмотреть файл

@ -249,9 +249,9 @@ function waitForProperty(dbg, property) {
});
}
function setBreakpoint(sourceClient, location) {
function setBreakpoint(threadClient, location) {
dump("Setting breakpoint.\n");
return sourceClient.setBreakpoint(location);
return threadClient.setBreakpoint(location, {});
}
function getPrototypeAndProperties(objClient) {

Просмотреть файл

@ -36,7 +36,7 @@ const testBlackBox = async function() {
packet.frame.where.actor
);
await setBreakpoint(bpSource, { line: 2 });
await setBreakpoint(gThreadClient, { sourceUrl: bpSource.url, line: 2 });
await resume(gThreadClient);
let sourceForm = await getSourceForm(gThreadClient, BLACK_BOXED_URL);

Просмотреть файл

@ -43,11 +43,8 @@ function test_black_box() {
function runWithSource(packet) {
const source = gThreadClient.source(packet.source);
source.setBreakpoint({
line: 2,
}).then(function() {
gThreadClient.resume(test_black_box_breakpoint);
});
gThreadClient.setBreakpoint({ sourceUrl: source.url, line: 2 }, {});
gThreadClient.resume(test_black_box_breakpoint);
}
});

Просмотреть файл

@ -11,7 +11,6 @@
var gDebuggee;
var gClient;
var gThreadClient;
var gBpClient;
function run_test() {
initTestDebuggerServer();
@ -33,8 +32,7 @@ const SOURCE_URL = "http://example.com/source.js";
function test_black_box() {
gClient.addOneTimeListener("paused", async function(event, packet) {
const source = await getSourceById(gThreadClient, packet.frame.where.actor);
const [, bpClient] = await source.setBreakpoint({ line: 4 });
gBpClient = bpClient;
gThreadClient.setBreakpoint({ sourceUrl: source.url, line: 4 }, {});
await gThreadClient.resume();
test_black_box_dbg_statement();
});
@ -79,7 +77,9 @@ function test_black_box_dbg_statement() {
Assert.equal(packet.why.type, "breakpoint",
"We should pass over the debugger statement.");
await gBpClient.remove();
const source = await getSourceById(gThreadClient, packet.frame.where.actor);
gThreadClient.removeBreakpoint({ sourceUrl: source.url, line: 4 }, {});
await gThreadClient.resume();
await test_unblack_box_dbg_statement(sourceClient);
});

Просмотреть файл

@ -40,9 +40,8 @@ function test_black_box() {
function runWithSource(packet) {
const source = gThreadClient.source(packet.source);
source.setBreakpoint({
line: 2,
}).then(test_black_box_paused);
gThreadClient.setBreakpoint({ sourceUrl: source.url, line: 2 }, {});
test_black_box_paused();
}
});

Просмотреть файл

@ -31,8 +31,8 @@ function run_test() {
const { sources } = await getSources(threadClient);
const sourceClient = threadClient.source(sources[0]);
await setBreakpoint(sourceClient, { line: 7 });
await setBreakpoint(sourceClient, { line: 11 });
await setBreakpoint(threadClient, { sourceUrl: sourceClient.url, line: 7 });
await setBreakpoint(threadClient, { sourceUrl: sourceClient.url, line: 11 });
// 1. lets blackbox function a, and assert that we pause in b
const range = {start: { line: 6, column: 0 }, end: { line: 8, colum: 1 }};

Просмотреть файл

@ -17,9 +17,9 @@ add_task(threadClientTest(async ({ threadClient, debuggee }) => {
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 3 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 3 };
const [, bpClient] = await source.setBreakpoint(location);
threadClient.setBreakpoint(location, {});
await threadClient.resume();
packet = await waitForPause(threadClient);
@ -29,13 +29,11 @@ add_task(threadClientTest(async ({ threadClient, debuggee }) => {
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
info("Check that the breakpoint worked.");
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
await bpClient.remove();
await threadClient.resume();
})();

Просмотреть файл

@ -11,11 +11,11 @@
add_task(threadClientTest(({ threadClient, debuggee }) => {
return new Promise((resolve) => {
threadClient.addOneTimeListener("paused", async function(event, packet) {
const location = { line: debuggee.line0 + 3 };
const source = await getSourceById(
threadClient,
packet.frame.where.actor
);
const location = { sourceUrl: source.url, line: debuggee.line0 + 3 };
threadClient.resume();
@ -25,15 +25,8 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
Assert.equal(packet.why.type, "interrupted");
});
source.setBreakpoint(location).then(function() {
executeSoon(resolve);
}, function(response) {
// Eval scripts don't stick around long enough for the breakpoint to be set,
// so just make sure we got the expected response from the actor.
Assert.notEqual(response.error, "noScript");
executeSoon(resolve);
});
threadClient.setBreakpoint(location, {});
executeSoon(resolve);
});
/* eslint-disable */

Просмотреть файл

@ -15,32 +15,27 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 3 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 3 };
source.setBreakpoint(location).then(function([response, bpClient]) {
// actualLocation is not returned when breakpoints don't skip forward.
Assert.equal(response.actualLocation, undefined);
threadClient.setBreakpoint(location, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
// Check that the breakpoint worked.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
// Remove the breakpoint.
bpClient.remove(function(response) {
threadClient.resume(resolve);
});
});
// Continue until the breakpoint is hit.
threadClient.resume();
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
threadClient.resume(resolve);
});
// Continue until the breakpoint is hit.
threadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -16,35 +16,33 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 2 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 2 };
source.setBreakpoint(location).then(function([response, bpClient]) {
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.a, undefined);
threadClient.setBreakpoint(location, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
// Check that the breakpoint worked.
Assert.equal(debuggee.a, undefined);
// Remove the breakpoint.
bpClient.remove(function(response) {
done = true;
threadClient.addOneTimeListener("paused",
function(event, packet) {
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
done = true;
threadClient.addOneTimeListener("paused",
function(event, packet) {
// The breakpoint should not be hit again.
threadClient.resume(function() {
Assert.ok(false);
});
});
threadClient.resume();
});
});
// Continue until the breakpoint is hit.
threadClient.resume(function() {
Assert.ok(false);
});
});
threadClient.resume();
});
// Continue until the breakpoint is hit.
threadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -16,40 +16,36 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 3 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 3 };
source.setBreakpoint(location).then(function([response, bpClient]) {
// actualLocation is not returned when breakpoints don't skip forward.
Assert.equal(response.actualLocation, undefined);
threadClient.setBreakpoint(location, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
// Check that the breakpoint worked.
Assert.equal(debuggee.i, 0);
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.i, 0);
Assert.equal(debuggee.i, 1);
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.i, 1);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
// Remove the breakpoint.
bpClient.remove(function(response) {
threadClient.resume(resolve);
});
});
// Continue until the breakpoint is hit again.
threadClient.resume();
threadClient.resume(resolve);
});
// Continue until the breakpoint is hit.
// Continue until the breakpoint is hit again.
threadClient.resume();
});
// Continue until the breakpoint is hit.
threadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -16,41 +16,37 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 2 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 2 };
source.setBreakpoint(location).then(function([response, bpClient]) {
// actualLocation is not returned when breakpoints don't skip forward.
Assert.equal(response.actualLocation, undefined);
threadClient.setBreakpoint(location, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
// Check that the breakpoint worked.
Assert.equal(debuggee.a, undefined);
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.a, undefined);
Assert.equal(debuggee.a.b, 1);
Assert.equal(debuggee.res, undefined);
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
// Check that the breakpoint worked.
Assert.equal(debuggee.a.b, 1);
Assert.equal(debuggee.res, undefined);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
// Remove the breakpoint.
bpClient.remove(function(response) {
threadClient.resume(resolve);
});
});
// Continue until the breakpoint is hit again.
threadClient.resume();
threadClient.resume(resolve);
});
// Continue until the breakpoint is hit.
// Continue until the breakpoint is hit again.
threadClient.resume();
});
// Continue until the breakpoint is hit.
threadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -16,65 +16,67 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 2 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 2 };
source.setBreakpoint(location).then(async function([response, bpClient]) {
const testCallbacks = [
function(packet) {
// Check that the stepping worked.
Assert.equal(packet.frame.where.line, debuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Entered the foo function call frame.
Assert.equal(packet.frame.where.line, location.line);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// At the end of the foo function call frame.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Check that the breakpoint wasn't the reason for this pause, but
// that the frame is about to be popped while stepping.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
Assert.equal(packet.frame.where.line, debuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, debuggee.line0 + 7);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
},
];
threadClient.setBreakpoint(location, {});
for (const callback of testCallbacks) {
const waiter = waitForPause(threadClient);
threadClient.stepIn();
const packet = await waiter;
callback(packet);
}
const testCallbacks = [
function(packet) {
// Check that the stepping worked.
Assert.equal(packet.frame.where.line, debuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Entered the foo function call frame.
Assert.equal(packet.frame.where.line, location.line);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// At the end of the foo function call frame.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Check that the breakpoint wasn't the reason for this pause, but
// that the frame is about to be popped while stepping.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
Assert.equal(packet.frame.where.line, debuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, debuggee.line0 + 7);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
},
];
// Remove the breakpoint and finish.
for (const callback of testCallbacks) {
const waiter = waitForPause(threadClient);
threadClient.stepIn();
await waiter;
bpClient.remove(() => threadClient.resume(resolve));
});
const packet = await waiter;
callback(packet);
}
// Remove the breakpoint and finish.
const waiter = waitForPause(threadClient);
threadClient.stepIn();
await waiter;
threadClient.removeBreakpoint(location);
threadClient.resume(resolve);
});
/* eslint-disable */

Просмотреть файл

@ -16,63 +16,63 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { line: debuggee.line0 + 2 };
const location = { sourceUrl: source.url, line: debuggee.line0 + 2 };
source.setBreakpoint(location).then(async function([response, bpClient]) {
const testCallbacks = [
function(packet) {
// Check that the stepping worked.
Assert.equal(packet.frame.where.line, debuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Reached the breakpoint.
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
Assert.notEqual(packet.why.type, "resumeLimit");
},
function(packet) {
// Stepped to the closing brace of the function.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// The frame is about to be popped while stepping.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
Assert.equal(packet.frame.where.line, debuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, debuggee.line0 + 7);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
},
];
threadClient.setBreakpoint(location, {});
const testCallbacks = [
function(packet) {
// Check that the stepping worked.
Assert.equal(packet.frame.where.line, debuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Reached the breakpoint.
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.why.type, "breakpoint");
Assert.notEqual(packet.why.type, "resumeLimit");
},
function(packet) {
// Stepped to the closing brace of the function.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// The frame is about to be popped while stepping.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(debuggee.a, 1);
Assert.equal(debuggee.b, undefined);
Assert.equal(packet.frame.where.line, debuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, debuggee.line0 + 7);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
},
];
for (const callback of testCallbacks) {
const waiter = waitForPause(threadClient);
threadClient.stepOver();
const packet = await waiter;
callback(packet);
}
// Remove the breakpoint and finish.
for (const callback of testCallbacks) {
const waiter = waitForPause(threadClient);
threadClient.stepOver();
await waiter;
bpClient.remove(() => threadClient.resume(resolve));
});
const packet = await waiter;
callback(packet);
}
// Remove the breakpoint and finish.
const waiter = waitForPause(threadClient);
threadClient.stepOver();
await waiter;
threadClient.removeBreakpoint(location);
threadClient.resume(resolve);
});
/* eslint-disable */

Просмотреть файл

@ -17,37 +17,36 @@ add_task(threadClientTest(({ threadClient, debuggee, client }) => {
packet.frame.where.actor
);
const location = {
sourceUrl: source.url,
line: debuggee.line0 + 1,
column: 55,
};
let timesBreakpointHit = 0;
source.setBreakpoint(location).then(function([response, bpClient]) {
threadClient.addListener("paused", function onPaused(event, packet) {
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.frame.where.column, location.column);
threadClient.setBreakpoint(location, {});
Assert.equal(debuggee.acc, timesBreakpointHit);
Assert.equal(packet.frame.environment.bindings.variables.i.value,
timesBreakpointHit);
threadClient.addListener("paused", function onPaused(event, packet) {
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);
Assert.equal(packet.frame.where.column, location.column);
if (++timesBreakpointHit === 3) {
threadClient.removeListener("paused", onPaused);
bpClient.remove(function(response) {
threadClient.resume(resolve);
});
} else {
threadClient.resume();
}
});
Assert.equal(debuggee.acc, timesBreakpointHit);
Assert.equal(packet.frame.environment.bindings.variables.i.value,
timesBreakpointHit);
// Continue until the breakpoint is hit.
threadClient.resume();
if (++timesBreakpointHit === 3) {
threadClient.removeListener("paused", onPaused);
threadClient.removeBreakpoint(location);
threadClient.resume(resolve);
} else {
threadClient.resume();
}
});
// Continue until the breakpoint is hit.
threadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -51,9 +51,8 @@ function setBreakpoint(packet, threadClient, client) {
);
client.addOneTimeListener("resumed", resolve);
source.setBreakpoint({ line: 3 }).then(() => {
threadClient.resume();
});
threadClient.setBreakpoint({ sourceUrl: source.url, line: 3 }, {});
threadClient.resume();
});
}

Просмотреть файл

@ -26,17 +26,11 @@ function setUpCode(debuggee) {
}
add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const source = await getSource(threadClient, URL);
const [response ] = await setBreakpoint(source, {line: 2});
ok(!response.error);
const actor = response.actor;
ok(actor);
setBreakpoint(threadClient, { sourceUrl: URL, line: 2});
await executeOnNextTickAndWaitForPause(() => setUpCode(debuggee), client);
await resume(threadClient);
const packet = await executeOnNextTickAndWaitForPause(debuggee.test, client);
equal(packet.why.type, "breakpoint");
notEqual(packet.why.actors.indexOf(actor), -1);
}));

Просмотреть файл

@ -34,13 +34,7 @@ const testBreakpoint = async function(threadResponse, targetFront,
// Set a breakpoint in the test source.
const source = await getSource(threadClient, "test.js");
const [response ] = await setBreakpoint(source, {
line: 3,
});
ok(!response.error, "Shouldn't get an error setting the BP.");
ok(!response.actualLocation,
"Shouldn't get an actualLocation, the location we provided was good.");
const bpActor = response.actor;
setBreakpoint(threadClient, { sourceUrl: source.url, line: 3 });
await resume(threadClient);
@ -57,8 +51,6 @@ const testBreakpoint = async function(threadResponse, targetFront,
gClient);
equal(bpPause1.why.type, "breakpoint",
"Should pause because of hitting our breakpoint (not debugger statement).");
equal(bpPause1.why.actors[0], bpActor,
"And the breakpoint actor should be correct.");
const dbgStmtPause1 = await executeOnNextTickAndWaitForPause(() => resume(threadClient),
gClient);
equal(dbgStmtPause1.why.type, "debuggerStatement",
@ -72,8 +64,6 @@ const testBreakpoint = async function(threadResponse, targetFront,
gClient);
equal(bpPause2.why.type, "breakpoint",
"Should pause because of hitting our breakpoint (not debugger statement).");
equal(bpPause2.why.actors[0], bpActor,
"And the breakpoint actor should be correct.");
const dbgStmtPause2 = await executeOnNextTickAndWaitForPause(() => resume(threadClient),
gClient);
equal(dbgStmtPause2.why.type, "debuggerStatement",

Просмотреть файл

@ -22,17 +22,16 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
packet.frame.where.actor
);
const location = {
sourceUrl: source.url,
line: debuggee.line0 + 8,
};
const [res, bpClient] = await setBreakpoint(source, location);
ok(!res.error);
setBreakpoint(threadClient, location);
await resume(threadClient);
packet = await waitForPause(client);
Assert.equal(packet.type, "paused");
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.why.actors[0], bpClient.actor);
Assert.equal(packet.frame.where.actor, source.actor);
Assert.equal(packet.frame.where.line, location.line);

Просмотреть файл

@ -34,28 +34,26 @@ function test_simple_breakpoint() {
gThreadClient,
packet.frame.where.actor
);
source.setBreakpoint({
line: 3,
options: { condition: "a === 1" },
}).then(function([response, bpClient]) {
gThreadClient.addOneTimeListener("paused", function(event, packet) {
Assert.equal(hitBreakpoint, false);
hitBreakpoint = true;
const location = { sourceUrl: source.url, line: 3 };
gThreadClient.setBreakpoint(location, { condition: "a === 1" });
gThreadClient.addOneTimeListener("paused", function(event, packet) {
Assert.equal(hitBreakpoint, false);
hitBreakpoint = true;
// Check the return value.
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.frame.where.line, 3);
// Check the return value.
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.frame.where.line, 3);
// Remove the breakpoint.
bpClient.remove(function(response) {
gThreadClient.resume(function() {
finishClient(gClient);
});
});
// Remove the breakpoint.
gThreadClient.removeBreakpoint(location);
gThreadClient.resume(function() {
finishClient(gClient);
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -32,29 +32,25 @@ function test_simple_breakpoint() {
gThreadClient,
packet.frame.where.actor
);
await source.setBreakpoint({
line: 3,
options: { condition: "a === 2" },
});
source.setBreakpoint({
line: 4,
options: { condition: "a === 1" },
}).then(function([response, bpClient]) {
gThreadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.frame.where.line, 4);
const location1 = { sourceUrl: source.url, line: 3 };
gThreadClient.setBreakpoint(location1, { condition: "a === 2" });
const location2 = { sourceUrl: source.url, line: 4 };
gThreadClient.setBreakpoint(location2, { condition: "a === 1" });
gThreadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.why.type, "breakpoint");
Assert.equal(packet.frame.where.line, 4);
// Remove the breakpoint.
bpClient.remove(function(response) {
gThreadClient.resume(function() {
finishClient(gClient);
});
});
// Remove the breakpoint.
gThreadClient.removeBreakpoint(location2);
gThreadClient.resume(function() {
finishClient(gClient);
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -32,25 +32,23 @@ function test_simple_breakpoint() {
gThreadClient,
packet.frame.where.actor
);
source.setBreakpoint({
line: 3,
options: { condition: "throw new Error()" },
}).then(function([response, bpClient]) {
gThreadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.why.type, "breakpointConditionThrown");
Assert.equal(packet.frame.where.line, 3);
const location = { sourceUrl: source.url, line: 3 };
gThreadClient.setBreakpoint(location, { condition: "throw new Error()" });
gThreadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.why.type, "breakpointConditionThrown");
Assert.equal(packet.frame.where.line, 3);
// Remove the breakpoint.
bpClient.remove(function(response) {
gThreadClient.resume(function() {
finishClient(gClient);
});
});
// Remove the breakpoint.
gThreadClient.removeBreakpoint(location);
gThreadClient.resume(function() {
finishClient(gClient);
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
// Continue until the breakpoint is hit.
gThreadClient.resume();
});
/* eslint-disable */

Просмотреть файл

@ -34,10 +34,10 @@ function test_simple_breakpoint() {
);
// Set a logpoint which should invoke console.log.
await source.setBreakpoint({
gThreadClient.setBreakpoint({
sourceUrl: source.url,
line: 4,
options: { logValue: "a" },
});
}, { logValue: "a" });
// Execute the rest of the code.
gThreadClient.resume();

Просмотреть файл

@ -34,10 +34,10 @@ function test_simple_breakpoint() {
);
// Set a logpoint which should invoke console.log.
await source.setBreakpoint({
gThreadClient.setBreakpoint({
sourceUrl: source.url,
line: 5,
options: { logValue: "a", condition: "a === 5" },
});
}, { logValue: "a", condition: "a === 5" });
// Execute the rest of the code.
gThreadClient.resume();

Просмотреть файл

@ -6,18 +6,11 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const promise = waitForNewSource(threadClient, SOURCE_URL);
loadSubScript(SOURCE_URL, debuggee);
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 4, column: 2 };
let [packet, breakpointClient] = await setBreakpoint(
sourceClient,
location
);
const location = { sourceUrl: source.url, line: 4, column: 2 };
setBreakpoint(threadClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
@ -25,7 +18,6 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
Assert.equal(frame.where.actor, source.actor);

Просмотреть файл

@ -6,20 +6,13 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const promise = waitForNewSource(threadClient, SOURCE_URL);
loadSubScript(SOURCE_URL, debuggee);
const { source } = await promise;
const sourceClient = threadClient.source(source);
// Pause inside of the nested function so we can make sure that we don't
// add any other breakpoints at other places on this line.
const location = { line: 3, column: 47 };
let [packet, breakpointClient] = await setBreakpoint(
sourceClient,
location
);
const location = { sourceUrl: source.url, line: 3, column: 47 };
setBreakpoint(threadClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
@ -27,7 +20,6 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;

Просмотреть файл

@ -6,18 +6,11 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const promise = waitForNewSource(threadClient, SOURCE_URL);
loadSubScript(SOURCE_URL, debuggee);
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 4, column: 42 };
let [packet, breakpointClient] = await setBreakpoint(
sourceClient,
location
);
const location = { sourceUrl: source.url, line: 4, column: 42 };
setBreakpoint(threadClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
@ -25,7 +18,6 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;

Просмотреть файл

@ -6,20 +6,13 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const promise = waitForNewSource(threadClient, SOURCE_URL);
loadSubScript(SOURCE_URL, debuggee);
const { source } = await promise;
const sourceClient = threadClient.source(source);
// Pause inside of the nested function so we can make sure that we don't
// add any other breakpoints at other places on this line.
const location = { line: 3, column: 81 };
let [packet, breakpointClient] = await setBreakpoint(
sourceClient,
location
);
const location = { sourceUrl: source.url, line: 3, column: 81 };
setBreakpoint(threadClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
@ -27,7 +20,6 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;

Просмотреть файл

@ -8,14 +8,11 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client, targetFront }
Cu.forceGC(); Cu.forceGC(); Cu.forceGC();
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 6, column: 17 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: source.url, line: 6, column: 17 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
reload(targetFront).then(function() {
loadSubScriptWithOptions(SOURCE_URL, {target: debuggee, ignoreCache: true});
});
@ -24,10 +21,8 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client, targetFront }
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;
Assert.equal(where.actor, source.actor);
Assert.equal(where.line, location.line);
Assert.equal(where.column, location.column);
const variables = frame.environment.bindings.variables;

Просмотреть файл

@ -6,21 +6,17 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const promise = waitForNewSource(threadClient, SOURCE_URL);
loadSubScript(SOURCE_URL, debuggee);
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 4, column: 17 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: source.url, line: 4, column: 17 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
Assert.equal(packet.type, "paused");
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;
Assert.equal(where.actor, source.actor);

Просмотреть файл

@ -8,14 +8,11 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client, targetFront }
Cu.forceGC(); Cu.forceGC(); Cu.forceGC();
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 7 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: source.url, line: 7 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
reload(targetFront).then(function() {
loadSubScriptWithOptions(SOURCE_URL, {target: debuggee, ignoreCache: true});
});
@ -24,10 +21,8 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client, targetFront }
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;
Assert.equal(where.actor, source.actor);
Assert.equal(where.line, location.line);
const variables = frame.environment.bindings.variables;
Assert.equal(variables.a.value, 1);

Просмотреть файл

@ -8,19 +8,16 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 4 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: sourceClient.url, line: 4 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
let packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
Assert.equal(packet.type, "paused");
let why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
let frame = packet.frame;
let where = frame.where;
Assert.equal(where.actor, source.actor);
@ -36,7 +33,6 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
frame = packet.frame;
where = frame.where;
Assert.equal(where.actor, source.actor);

Просмотреть файл

@ -8,19 +8,16 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 4 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: sourceClient.url, line: 4 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
Assert.equal(packet.type, "paused");
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;
Assert.equal(where.actor, source.actor);

Просмотреть файл

@ -8,19 +8,16 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const { source } = await promise;
const sourceClient = threadClient.source(source);
const location = { line: 5 };
let [packet, breakpointClient] = await setBreakpoint(sourceClient, location);
Assert.ok(!packet.isPending);
Assert.equal(false, "actualLocation" in packet);
const location = { sourceUrl: sourceClient.url, line: 5 };
setBreakpoint(threadClient, location);
packet = await executeOnNextTickAndWaitForPause(function() {
const packet = await executeOnNextTickAndWaitForPause(function() {
Cu.evalInSandbox("f()", debuggee);
}, client);
Assert.equal(packet.type, "paused");
const why = packet.why;
Assert.equal(why.type, "breakpoint");
Assert.equal(why.actors.length, 1);
Assert.equal(why.actors[0], breakpointClient.actor);
const frame = packet.frame;
const where = frame.where;
Assert.equal(where.actor, source.actor);

Просмотреть файл

@ -18,7 +18,7 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
threadClient,
dbgStmt.frame.where.actor
);
await source.setBreakpoint({ line: 7 });
await threadClient.setBreakpoint({ sourceUrl: source.url, line: 7 }, {});
dumpn("Step in to innerFunction");
const step1 = await stepIn(client, threadClient);

Просмотреть файл

@ -128,8 +128,10 @@ skip-if = true # breakpoint sliding is not supported bug 1525685
[test_breakpoint-13.js]
[test_breakpoint-14.js]
[test_breakpoint-15.js]
skip-if = true # tests for breakpoint actors are obsolete bug 1524374
[test_breakpoint-16.js]
[test_breakpoint-17.js]
skip-if = true # tests for breakpoint actors are obsolete bug 1524374
[test_breakpoint-18.js]
[test_breakpoint-19.js]
skip-if = true
@ -209,6 +211,7 @@ skip-if = true # breakpoint sliding is not supported bug 1525685
[test_source-02.js]
[test_wasm_source-01.js]
[test_breakpoint-actor-map.js]
skip-if = true # tests for breakpoint actors are obsolete bug 1524374
[test_unsafeDereference.js]
[test_add_actors.js]
[test_ignore_caught_exceptions.js]

Просмотреть файл

@ -1,100 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const promise = require("devtools/shared/deprecated-sync-thenables");
const eventSource = require("devtools/shared/client/event-source");
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
/**
* Breakpoint clients are used to remove breakpoints that are no longer used.
*
* @param client DebuggerClient
* The debugger client parent.
* @param sourceClient SourceClient
* The source where this breakpoint exists
* @param actor string
* The actor ID for this breakpoint.
* @param location object
* The location of the breakpoint. This is an object with two properties:
* url and line.
* @param options object
* Any options associated with the breakpoint
*/
function BreakpointClient(client, sourceClient, actor, location, options) {
this._client = client;
this._actor = actor;
this.location = location;
this.location.actor = sourceClient.actor;
this.location.url = sourceClient.url;
this.source = sourceClient;
this.request = this._client.request;
this.options = options;
}
BreakpointClient.prototype = {
_actor: null,
get actor() {
return this._actor;
},
get _transport() {
return this._client._transport;
},
/**
* Remove the breakpoint from the server.
*/
remove: DebuggerClient.requester({
type: "delete",
}),
// Send a setOptions request to newer servers.
setOptionsRequester: DebuggerClient.requester({
type: "setOptions",
options: arg(0),
}, {
before(packet) {
this.options = packet.options;
return packet;
},
}),
/**
* Set any options for this breakpoint.
*/
setOptions: function(options) {
if (this._client.mainRoot.traits.nativeLogpoints) {
return this.setOptionsRequester(options).then(() => this);
}
// Older servers need to reinstall breakpoints when the condition changes.
const deferred = promise.defer();
const info = {
line: this.location.line,
column: this.location.column,
options,
};
// Remove the current breakpoint and add a new one with the specified
// information.
this.remove(response => {
if (response && response.error) {
deferred.reject(response);
return;
}
deferred.resolve(this.source.setBreakpoint(info).then(([, newBreakpoint]) => {
return newBreakpoint;
}));
});
return deferred;
},
};
eventSource(BreakpointClient.prototype);
module.exports = BreakpointClient;

Просмотреть файл

@ -6,7 +6,6 @@
DevToolsModules(
'array-buffer-client.js',
'breakpoint-client.js',
'connection-manager.js',
'constants.js',
'debugger-client.js',

Просмотреть файл

@ -5,7 +5,6 @@
"use strict";
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
loader.lazyRequireGetter(this, "BreakpointClient", "devtools/shared/client/breakpoint-client");
const noop = () => {};
@ -149,87 +148,6 @@ SourceClient.prototype = {
});
},
/**
* Request to set a breakpoint in the specified location.
*
* @param object location
* The location and options of the breakpoint in
* the form of { line[, column, options] }.
*/
setBreakpoint: function({ line, column, options }) {
// A helper function that sets the breakpoint.
const doSetBreakpoint = callback => {
const location = {
line,
column,
};
const packet = {
to: this.actor,
type: "setBreakpoint",
location,
options,
};
// Older servers only support conditions, not a more general options
// object. Transform the packet to support the older format.
if (options && !this._client.mainRoot.traits.nativeLogpoints) {
delete packet.options;
if (options.logValue) {
// Emulate log points by setting a condition with a call to console.log,
// which always returns false so the server will never pause.
packet.condition = `console.log(${options.logValue})`;
} else {
packet.condition = options.condition;
}
}
return this._client.request(packet).then(response => {
// Ignoring errors, since the user may be setting a breakpoint in a
// dead script that will reappear on a page reload.
let bpClient;
if (response.actor) {
bpClient = new BreakpointClient(
this._client,
this,
response.actor,
location,
options
);
}
if (callback) {
callback();
}
return [response, bpClient];
});
};
// With async sourcemap processing removed from the server, it is not
// necessary for clients to pause the debuggee before adding breakpoints.
if (this._client.mainRoot.traits.breakpointWhileRunning) {
return doSetBreakpoint();
}
// If the debuggee is paused, just set the breakpoint.
if (this._activeThread.paused) {
return doSetBreakpoint();
}
// Otherwise, force a pause in order to set the breakpoint.
return this._activeThread.interrupt().then(response => {
if (response.error) {
// Can't set the breakpoint if pausing failed.
return response;
}
const { type, why } = response;
const cleanUp = type == "paused" && why.type == "interrupted"
? () => this._activeThread.resume()
: noop;
return doSetBreakpoint(cleanUp);
});
},
setPausePoints: function(pausePoints) {
const packet = {
to: this._form.actor,

Просмотреть файл

@ -663,6 +663,17 @@ ThreadClient.prototype = {
return this._lastPausePacket;
},
setBreakpoint: DebuggerClient.requester({
type: "setBreakpoint",
location: arg(0),
options: arg(1),
}),
removeBreakpoint: DebuggerClient.requester({
type: "removeBreakpoint",
location: arg(0),
}),
/**
* Requests to set XHR breakpoint
* @param string path

Просмотреть файл

@ -1,22 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {Arg, generateActorSpec} = require("devtools/shared/protocol");
const breakpointSpec = generateActorSpec({
typeName: "breakpoint",
methods: {
delete: {},
setOptions: {
request: {
options: Arg(0, "nullable:json"),
},
},
},
});
exports.breakpointSpec = breakpointSpec;

Просмотреть файл

@ -42,12 +42,6 @@ const Types = exports.__TypesForTests = [
spec: "devtools/shared/specs/animation",
front: "devtools/shared/fronts/animation",
},
/* breakpoint has old fashion client and no front */
{
types: ["breakpoint"],
spec: "devtools/shared/specs/breakpoint",
front: null,
},
{
types: ["frame-snapshot", "canvas"],
spec: "devtools/shared/specs/canvas",

Просмотреть файл

@ -14,7 +14,6 @@ DevToolsModules(
'accessibility.js',
'actor-registry.js',
'animation.js',
'breakpoint.js',
'canvas.js',
'changes.js',
'css-properties.js',

Просмотреть файл

@ -9,6 +9,17 @@ const threadSpec = generateActorSpec({
typeName: "context",
methods: {
setBreakpoint: {
request: {
location: Arg(0, "json"),
options: Arg(1, "json"),
},
},
removeBreakpoint: {
request: {
location: Arg(0, "json"),
},
},
setXHRBreakpoint: {
request: {
path: Arg(0, "string"),

Просмотреть файл

@ -55,16 +55,6 @@ const sourceSpec = generateActorSpec({
unblackbox: {
request: { range: Arg(0, "nullable:json") },
},
setBreakpoint: {
request: {
location: {
line: Arg(0, "number"),
column: Arg(1, "nullable:number"),
},
options: Arg(2, "nullable:json"),
},
response: RetVal("json"),
},
},
});