Skip to content
This repository has been archived by the owner on Oct 2, 2021. It is now read-only.

Commit

Permalink
Add conditional bps and stop using deprecated API -
Browse files Browse the repository at this point in the history
Fix #10 and fix #73
  • Loading branch information
roblourens committed Sep 21, 2016
1 parent af88757 commit 69ab75f
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 150 deletions.
4 changes: 2 additions & 2 deletions src/chrome/chromeConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ export class ChromeConnection {
return this.sendMessage('Debugger.setBreakpoint', <Chrome.Debugger.SetBreakpointParams>{ location, condition });
}

public debugger_setBreakpointByUrl(url: string, lineNumber: number, columnNumber: number): Promise<Chrome.Debugger.SetBreakpointByUrlResponse> {
return this.sendMessage('Debugger.setBreakpointByUrl', <Chrome.Debugger.SetBreakpointByUrlParams>{ url, lineNumber, columnNumber });
public debugger_setBreakpointByUrl(url: string, lineNumber: number, columnNumber: number, condition?: string): Promise<Chrome.Debugger.SetBreakpointByUrlResponse> {
return this.sendMessage('Debugger.setBreakpointByUrl', <Chrome.Debugger.SetBreakpointByUrlParams>{ url, lineNumber, columnNumber, condition });
}

public debugger_removeBreakpoint(breakpointId: string): Promise<Chrome.Response> {
Expand Down
13 changes: 7 additions & 6 deletions src/chrome/chromeDebugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ export abstract class ChromeDebugAdapter extends BaseDebugAdapter {
}
],
supportsConfigurationDoneRequest: true,
supportsSetVariable: true
supportsSetVariable: true,
supportsConditionalBreakpoints: true
};
}

Expand Down Expand Up @@ -386,7 +387,7 @@ export abstract class ChromeDebugAdapter extends BaseDebugAdapter {
// DebugProtocol sends all current breakpoints for the script. Clear all scripts for the breakpoint then add all of them
const setBreakpointsPFailOnError = this._setBreakpointsRequestQ
.then(() => this.clearAllBreakpoints(targetScriptUrl))
.then(() => this.addBreakpoints(targetScriptUrl, args.lines, args.cols))
.then(() => this.addBreakpoints(targetScriptUrl, args.breakpoints))
.then(responses => ({ breakpoints: this.chromeBreakpointResponsesToODPBreakpoints(targetScriptUrl, responses, args.lines) }));

const setBreakpointsPTimeout = utils.promiseTimeout(setBreakpointsPFailOnError, /*timeoutMs*/2000, 'Set breakpoints request timed out');
Expand Down Expand Up @@ -430,19 +431,19 @@ export abstract class ChromeDebugAdapter extends BaseDebugAdapter {
* Responses from setBreakpointByUrl are transformed to look like the response from setBreakpoint, so they can be
* handled the same.
*/
protected addBreakpoints(url: string, lines: number[], cols?: number[]): Promise<Chrome.Debugger.SetBreakpointResponse[]> {
protected addBreakpoints(url: string, breakpoints: DebugProtocol.SourceBreakpoint[]): Promise<Chrome.Debugger.SetBreakpointResponse[]> {
let responsePs: Promise<Chrome.Debugger.SetBreakpointResponse>[];
if (url.startsWith(ChromeDebugAdapter.PLACEHOLDER_URL_PROTOCOL)) {
// eval script with no real url - use debugger_setBreakpoint
const scriptId = utils.lstrip(url, ChromeDebugAdapter.PLACEHOLDER_URL_PROTOCOL);
responsePs = lines.map((lineNumber, i) => this._chromeConnection.debugger_setBreakpoint({ scriptId, lineNumber, columnNumber: cols ? cols[i] : 0 }));
responsePs = breakpoints.map(({ line, column = 0, condition }, i) => this._chromeConnection.debugger_setBreakpoint({ scriptId, lineNumber: line, columnNumber: column }, condition));
} else {
// script that has a url - use debugger_setBreakpointByUrl so that Chrome will rebind the breakpoint immediately
// after refreshing the page. This is the only way to allow hitting breakpoints in code that runs immediately when
// the page loads.
const script = this._scriptsByUrl.get(url);
responsePs = lines.map((lineNumber, i) => {
return this._chromeConnection.debugger_setBreakpointByUrl(url, lineNumber, cols ? cols[i] : 0).then(response => {
responsePs = breakpoints.map(({ line, column = 0, condition }, i) => {
return this._chromeConnection.debugger_setBreakpointByUrl(url, line, column, condition).then(response => {
// Now convert the response to a SetBreakpointResponse so both response types can be handled the same
const locations = response.result.locations;
return <Chrome.Debugger.SetBreakpointResponse>{
Expand Down
43 changes: 17 additions & 26 deletions src/transformers/baseSourceMapTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export class BaseSourceMapTransformer {
private _requestSeqToSetBreakpointsArgs: Map<number, ISetBreakpointsArgs>;
private _allRuntimeScriptPaths: Set<string>;
private _pendingBreakpointsByPath = new Map<string, IPendingBreakpoint>();
private _authoredPathsToMappedBPLines: Map<string, number[]>;
private _authoredPathsToMappedBPCols: Map<string, number[]>;
private _authoredPathsToMappedBPs: Map<string, DebugProtocol.SourceBreakpoint[]>;

constructor(sourceHandles: Handles<ISourceContainer>) {
this._sourceHandles = sourceHandles;
Expand All @@ -50,8 +49,7 @@ export class BaseSourceMapTransformer {
this._sourceMaps = new SourceMaps(args.webRoot, args.sourceMapPathOverrides);
this._requestSeqToSetBreakpointsArgs = new Map<number, ISetBreakpointsArgs>();
this._allRuntimeScriptPaths = new Set<string>();
this._authoredPathsToMappedBPLines = new Map<string, number[]>();
this._authoredPathsToMappedBPCols = new Map<string, number[]>();
this._authoredPathsToMappedBPs = new Map<string, DebugProtocol.SourceBreakpoint[]>();
}
}

Expand Down Expand Up @@ -86,39 +84,32 @@ export class BaseSourceMapTransformer {
args.authoredPath = argsPath;
args.source.path = mappedPath;

// DebugProtocol doesn't send cols, but they need to be added from sourcemaps
const mappedCols = [];
const mappedLines = args.lines.map((line, i) => {
const mapped = this._sourceMaps.mapToGenerated(argsPath, line, /*column=*/0);
// DebugProtocol doesn't send cols yet, but they need to be added from sourcemaps
args.breakpoints.forEach(bp => {
const { line, column = 0 } = bp;
const mapped = this._sourceMaps.mapToGenerated(argsPath, line, column);
if (mapped) {
logger.log(`SourceMaps.setBP: Mapped ${argsPath}:${line + 1}:1 to ${mappedPath}:${mapped.line + 1}:${mapped.column + 1}`);
mappedCols[i] = mapped.column;
return mapped.line;
logger.log(`SourceMaps.setBP: Mapped ${argsPath}:${line + 1}:${column + 1} to ${mappedPath}:${mapped.line + 1}:${mapped.column + 1}`);
bp.line = mapped.line;
bp.column = mapped.column;
} else {
logger.log(`SourceMaps.setBP: Mapped ${argsPath} but not line ${line + 1}, column 1`);
mappedCols[i] = 0;
return line;
bp.column = column; // take 0 default if needed
}
});

this._authoredPathsToMappedBPLines.set(argsPath, mappedLines);
this._authoredPathsToMappedBPCols.set(argsPath, mappedCols);
this._authoredPathsToMappedBPs.set(argsPath, args.breakpoints);

// Include BPs from other files that map to the same file. Ensure the current file's breakpoints go first
args.lines = mappedLines;
args.cols = mappedCols;
this._sourceMaps.allMappedSources(mappedPath).forEach(sourcePath => {
if (sourcePath === argsPath) {
return;
}

const sourceBPLines = this._authoredPathsToMappedBPLines.get(sourcePath);
const sourceBPCols = this._authoredPathsToMappedBPCols.get(sourcePath);

if (sourceBPLines && sourceBPCols) {
const sourceBPs = this._authoredPathsToMappedBPs.get(sourcePath);
if (sourceBPs) {
// Don't modify the cached array
args.lines = args.lines.concat(sourceBPLines);
args.cols = args.cols.concat(sourceBPCols);
args.breakpoints = args.breakpoints.concat(sourceBPs);
}
});
} else if (this._allRuntimeScriptPaths.has(argsPath)) {
Expand Down Expand Up @@ -147,11 +138,11 @@ export class BaseSourceMapTransformer {
if (this._sourceMaps && this._requestSeqToSetBreakpointsArgs.has(requestSeq)) {
const args = this._requestSeqToSetBreakpointsArgs.get(requestSeq);
if (args.authoredPath) {
const sourceBPLines = this._authoredPathsToMappedBPLines.get(args.authoredPath);
if (sourceBPLines) {
const sourceBPs = this._authoredPathsToMappedBPs.get(args.authoredPath);
if (sourceBPs) {
// authoredPath is set, so the file was mapped to source.
// Remove breakpoints from files that map to the same file, and map back to source.
response.breakpoints = response.breakpoints.filter((_, i) => i < sourceBPLines.length);
response.breakpoints = response.breakpoints.filter((_, i) => i < sourceBPs.length);
response.breakpoints.forEach(bp => {
const mapped = this._sourceMaps.mapToAuthored(args.source.path, bp.line, bp.column);
if (mapped) {
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/lineNumberTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class LineNumberTransformer implements IDebugTransformer {
}

public setBreakpoints(args: DebugProtocol.SetBreakpointsArguments): void {
args.lines = args.lines.map(line => this.convertClientLineToTarget(line));
args.breakpoints.forEach(bp => bp.line = this.convertClientLineToTarget(bp.line));
}

public setBreakpointsResponse(response: ISetBreakpointsResponseBody): void {
Expand Down
Loading

0 comments on commit 69ab75f

Please sign in to comment.