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

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
roblourens committed Sep 25, 2017
1 parent 30857b5 commit 4a79029
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 73 deletions.
27 changes: 20 additions & 7 deletions src/chrome/chromeDebugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,27 +886,40 @@ export abstract class ChromeDebugAdapter implements IDebugAdapter {
protected onConsoleAPICalled(params: Crdp.Runtime.ConsoleAPICalledEvent): void {
const result = formatConsoleArguments(params);
if (result) {
this.logObjects(result.args, result.isError);
this.logObjects(result.args, result.isError, params.stackTrace);
}
}

private async logObjects(objs: Crdp.Runtime.RemoteObject[], isError = false): Promise<void> {
private async logObjects(objs: Crdp.Runtime.RemoteObject[], isError = false, stackTrace?: Crdp.Runtime.StackTrace): Promise<void> {
const category = isError ? 'stderr' : 'stdout';

// Shortcut the common log case to reduce unnecessary back and forth
let e: DebugProtocol.OutputEvent;
if (objs.length === 1 && objs[0].type === 'string') {
let msg = objs[0].value;
if (isError) {
msg = await this.mapFormattedException(msg);
}

const e = new OutputEvent(msg + '\n', category);
this._session.sendEvent(e);
return;
e = new OutputEvent(msg + '\n', category);
} else {
e = new OutputEvent('output', category);
e.body.variablesReference = this._variableHandles.create(new variables.LoggedObjects(objs), 'repl');
}

if (stackTrace && stackTrace.callFrames.length) {
const frame = stackTrace.callFrames[0];
const debuggerCF = this.runtimeCFToDebuggerCF(frame);
const stackFrame = this.callFrameToStackFrame(debuggerCF);
this._pathTransformer.fixStackFrame(stackFrame);
await this._sourceMapTransformer.fixStackFrame(stackFrame);
this._lineColTransformer.convertDebuggerLocationToClient(stackFrame);

e.body.source = stackFrame.source;
e.body.line = stackFrame.line;
e.body.column = stackFrame.column;
}

const e: DebugProtocol.OutputEvent = new OutputEvent('output', category);
e.body.variablesReference = this._variableHandles.create(new variables.LoggedObjects(objs), 'repl');
this._session.sendEvent(e);
}

Expand Down
3 changes: 3 additions & 0 deletions src/transformers/basePathTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export class BasePathTransformer {
public stackTraceResponse(response: IStackTraceResponseBody): void {
}

public fixStackFrame(stackFrame: DebugProtocol.StackFrame): void {
}

public getTargetPathFromClientPath(clientPath: string): string {
return clientPath;
}
Expand Down
72 changes: 39 additions & 33 deletions src/transformers/baseSourceMapTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as path from 'path';
import {DebugProtocol} from 'vscode-debugprotocol';

import {ISetBreakpointsArgs, ILaunchRequestArgs, IAttachRequestArgs,
ISetBreakpointsResponseBody, IInternalStackTraceResponseBody, IScopesResponseBody} from '../debugAdapterInterfaces';
ISetBreakpointsResponseBody, IInternalStackTraceResponseBody, IScopesResponseBody, IInternalStackFrame} from '../debugAdapterInterfaces';
import {MappedPosition, ISourcePathDetails} from '../sourceMaps/sourceMap';
import {SourceMaps} from '../sourceMaps/sourceMaps';
import * as utils from '../utils';
Expand Down Expand Up @@ -179,40 +179,46 @@ export class BaseSourceMapTransformer {
public async stackTraceResponse(response: IInternalStackTraceResponseBody): Promise<void> {
if (this._sourceMaps) {
await this._processingNewSourceMap;
response.stackFrames.forEach(stackFrame => this.fixStackFrame(stackFrame));
}
}

response.stackFrames.forEach(stackFrame => {
if (!stackFrame.source) {
return;
}
public async fixStackFrame(stackFrame: IInternalStackFrame): Promise<void> {
if (!this._sourceMaps) {
}

const mapped = this._sourceMaps.mapToAuthored(stackFrame.source.path, stackFrame.line, stackFrame.column);
if (mapped && utils.existsSync(mapped.source)) {
// Script was mapped to a valid path
stackFrame.source.path = mapped.source;
stackFrame.source.sourceReference = undefined;
stackFrame.source.name = path.basename(mapped.source);
stackFrame.line = mapped.line;
stackFrame.column = mapped.column;
stackFrame.isSourceMapped = true;
} else {
const inlinedSource = mapped && this._sourceMaps.sourceContentFor(mapped.source);
if (mapped && inlinedSource) {
// Clear the path and set the sourceReference - the client will ask for
// the source later and it will be returned from the sourcemap
stackFrame.source.name = path.basename(mapped.source);
stackFrame.source.path = mapped.source;
stackFrame.source.sourceReference = this.getSourceReferenceForScriptPath(mapped.source, inlinedSource);
stackFrame.source.origin = localize('origin.inlined.source.map', "read-only inlined content from source map");
stackFrame.line = mapped.line;
stackFrame.column = mapped.column;
stackFrame.isSourceMapped = true;
} else if (utils.existsSync(stackFrame.source.path)) {
// Script could not be mapped, but does exist on disk. Keep it and clear the sourceReference.
stackFrame.source.sourceReference = undefined;
stackFrame.source.origin = undefined;
}
}
});
if (!stackFrame.source) {
return;
}

await this._processingNewSourceMap;

const mapped = this._sourceMaps.mapToAuthored(stackFrame.source.path, stackFrame.line, stackFrame.column);
if (mapped && utils.existsSync(mapped.source)) {
// Script was mapped to a valid path
stackFrame.source.path = mapped.source;
stackFrame.source.sourceReference = undefined;
stackFrame.source.name = path.basename(mapped.source);
stackFrame.line = mapped.line;
stackFrame.column = mapped.column;
stackFrame.isSourceMapped = true;
} else {
const inlinedSource = mapped && this._sourceMaps.sourceContentFor(mapped.source);
if (mapped && inlinedSource) {
// Clear the path and set the sourceReference - the client will ask for
// the source later and it will be returned from the sourcemap
stackFrame.source.name = path.basename(mapped.source);
stackFrame.source.path = mapped.source;
stackFrame.source.sourceReference = this.getSourceReferenceForScriptPath(mapped.source, inlinedSource);
stackFrame.source.origin = localize('origin.inlined.source.map', "read-only inlined content from source map");
stackFrame.line = mapped.line;
stackFrame.column = mapped.column;
stackFrame.isSourceMapped = true;
} else if (utils.existsSync(stackFrame.source.path)) {
// Script could not be mapped, but does exist on disk. Keep it and clear the sourceReference.
stackFrame.source.sourceReference = undefined;
stackFrame.source.origin = undefined;
}
}
}

Expand Down
13 changes: 6 additions & 7 deletions src/transformers/lineNumberTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class LineColTransformer implements IDebugTransformer {
}
}

private convertClientLocationToDebugger(location: { line?: number; column?: number }): void {
public convertClientLocationToDebugger(location: { line?: number; column?: number }): void {
if (typeof location.line === 'number') {
location.line = this.convertClientLineToDebugger(location.line);
}
Expand All @@ -70,7 +70,7 @@ export class LineColTransformer implements IDebugTransformer {
}
}

private convertDebuggerLocationToClient(location: { line?: number; column?: number }): void {
public convertDebuggerLocationToClient(location: { line?: number; column?: number }): void {
if (typeof location.line === 'number') {
location.line = this.convertDebuggerLineToClient(location.line);
}
Expand All @@ -80,20 +80,19 @@ export class LineColTransformer implements IDebugTransformer {
}
}

// Should be stable but ...
private convertClientLineToDebugger(line: number): number {
public convertClientLineToDebugger(line: number): number {
return (<any>this._session).convertClientLineToDebugger(line);
}

private convertDebuggerLineToClient(line: number): number {
public convertDebuggerLineToClient(line: number): number {
return (<any>this._session).convertDebuggerLineToClient(line);
}

private convertClientColumnToDebugger(column: number): number {
public convertClientColumnToDebugger(column: number): number {
return (<any>this._session).convertClientColumnToDebugger(column);
}

private convertDebuggerColumnToClient(column: number): number {
public convertDebuggerColumnToClient(column: number): number {
return (<any>this._session).convertDebuggerColumnToClient(column);
}
}
23 changes: 13 additions & 10 deletions src/transformers/remotePathTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as fs from 'fs';
import {BasePathTransformer} from './basePathTransformer';

import {logger} from 'vscode-debugadapter';
import {DebugProtocol} from 'vscode-debugprotocol';
import * as utils from '../utils';
import * as errors from '../errors';
import {ISetBreakpointsArgs, ICommonRequestArgs, IAttachRequestArgs, ILaunchRequestArgs, IStackTraceResponseBody} from '../debugAdapterInterfaces';
Expand Down Expand Up @@ -68,17 +69,19 @@ export class RemotePathTransformer extends BasePathTransformer {
}

public stackTraceResponse(response: IStackTraceResponseBody): void {
response.stackFrames.forEach(frame => {
const remotePath = frame.source && frame.source.path;
if (remotePath) {
const localPath = this.getClientPathFromTargetPath(remotePath);
if (utils.existsSync(localPath)) {
frame.source.path = localPath;
frame.source.sourceReference = undefined;
frame.source.origin = undefined;
}
response.stackFrames.forEach(stackFrame => this.fixStackFrame(stackFrame));
}

public fixStackFrame(stackFrame: DebugProtocol.StackFrame): void {
const remotePath = stackFrame.source && stackFrame.source.path;
if (remotePath) {
const localPath = this.getClientPathFromTargetPath(remotePath);
if (utils.existsSync(localPath)) {
stackFrame.source.path = localPath;
stackFrame.source.sourceReference = undefined;
stackFrame.source.origin = undefined;
}
});
}
}

private shouldMapPaths(remotePath: string): boolean {
Expand Down
35 changes: 19 additions & 16 deletions src/transformers/urlPathTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {BasePathTransformer} from './basePathTransformer';
import {ISetBreakpointsArgs, ILaunchRequestArgs, IAttachRequestArgs, IStackTraceResponseBody} from '../debugAdapterInterfaces';
import * as utils from '../utils';
import {logger} from 'vscode-debugadapter';
import {DebugProtocol} from 'vscode-debugprotocol';
import * as ChromeUtils from '../chrome/chromeUtils';
import {ChromeDebugAdapter} from '../chrome/chromeDebugAdapter';

Expand Down Expand Up @@ -87,23 +88,25 @@ export class UrlPathTransformer extends BasePathTransformer {
}

public stackTraceResponse(response: IStackTraceResponseBody): void {
response.stackFrames.forEach(frame => {
if (frame.source && frame.source.path) {
// Try to resolve the url to a path in the workspace. If it's not in the workspace,
// just use the script.url as-is. It will be resolved or cleared by the SourceMapTransformer.
const clientPath = this.getClientPathFromTargetPath(frame.source.path) ||
ChromeUtils.targetUrlToClientPath(this._webRoot, frame.source.path);

// Incoming stackFrames have sourceReference and path set. If the path was resolved to a file in the workspace,
// clear the sourceReference since it's not needed.
if (clientPath) {
frame.source.path = clientPath;
frame.source.sourceReference = undefined;
frame.source.origin = undefined;
frame.source.name = path.basename(clientPath);
}
response.stackFrames.forEach(frame => this.fixStackFrame(frame));
}

public fixStackFrame(stackFrame: DebugProtocol.StackFrame): void {
if (stackFrame.source && stackFrame.source.path) {
// Try to resolve the url to a path in the workspace. If it's not in the workspace,
// just use the script.url as-is. It will be resolved or cleared by the SourceMapTransformer.
const clientPath = this.getClientPathFromTargetPath(stackFrame.source.path) ||
ChromeUtils.targetUrlToClientPath(this._webRoot, stackFrame.source.path);

// Incoming stackFrames have sourceReference and path set. If the path was resolved to a file in the workspace,
// clear the sourceReference since it's not needed.
if (clientPath) {
stackFrame.source.path = clientPath;
stackFrame.source.sourceReference = undefined;
stackFrame.source.origin = undefined;
stackFrame.source.name = path.basename(clientPath);
}
});
}
}

public getTargetPathFromClientPath(clientPath: string): string {
Expand Down

0 comments on commit 4a79029

Please sign in to comment.