Factor out sourcemaps and add tests
This commit is contained in:
Родитель
d9135b7313
Коммит
a5b11ed116
|
@ -13,18 +13,10 @@
|
|||
},
|
||||
{
|
||||
"name": "test",
|
||||
"type": "webkit",
|
||||
"program": "./webkit/test/index.html",
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": false,
|
||||
"outDir": "out"
|
||||
},
|
||||
{
|
||||
"name": "opendebug-node",
|
||||
"type": "node",
|
||||
"program": "./out/node/openDebugNode.js",
|
||||
"program": "./node_modules/gulp/bin/gulp.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [ "--server=4712" ],
|
||||
"args": [ "test" ],
|
||||
"sourceMaps": false,
|
||||
"outDir": "out"
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"taskName": "build-test-watch",
|
||||
"isWatching": true
|
||||
"taskName": "watch-build-test",
|
||||
"isWatching": true,
|
||||
"isTestCommand": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -35,7 +35,7 @@ export class AdapterProxy {
|
|||
(p, transformer) => {
|
||||
// If the transformer implements this command, give it a chance to modify the args. Otherwise skip it
|
||||
return request.command in transformer ?
|
||||
p.then(() => transformer[request.command](request.arguments)) :
|
||||
p.then(() => transformer[request.command](request.arguments, request.seq)) :
|
||||
p;
|
||||
}, Promise.resolve<void>());
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ export class AdapterProxy {
|
|||
// If the transformer implements this command, give it a chance to modify the args. Otherwise skip it
|
||||
const bodyTransformMethodName = request.command + "Response";
|
||||
return bodyTransformMethodName in transformer ?
|
||||
p.then(() => transformer[bodyTransformMethodName](body)) :
|
||||
p.then(() => transformer[bodyTransformMethodName](body, request.seq)) :
|
||||
p;
|
||||
}, Promise.resolve<void>());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import {ISourceMaps, SourceMaps} from './sourceMaps';
|
||||
|
||||
/**
|
||||
* If sourcemaps are enabled, converts from source files on the client side to runtime files on the target side
|
||||
*/
|
||||
export class SourceMapTransformer implements IDebugTransformer {
|
||||
private _sourceMaps: ISourceMaps;
|
||||
private _generatedCodeDirectory: string;
|
||||
private _requestSeqToSetBreakpointsArgs: Map<number, DebugProtocol.SetBreakpointsArguments>;
|
||||
|
||||
public initialize(args: IInitializeRequestArgs): void {
|
||||
if (args.sourceMaps) {
|
||||
this._sourceMaps = new SourceMaps(args.generatedCodeDirectory);
|
||||
this._generatedCodeDirectory = args.generatedCodeDirectory;
|
||||
this._requestSeqToSetBreakpointsArgs = new Map<number, DebugProtocol.SetBreakpointsArguments>();
|
||||
}
|
||||
}
|
||||
|
||||
public launch(args: ILaunchRequestArgs): void {
|
||||
// Can html files be sourcemapped? May as well try.
|
||||
if (this._sourceMaps && args.program) {
|
||||
const generatedPath = this._sourceMaps.MapPathFromSource(args.program);
|
||||
if (generatedPath) {
|
||||
args.program = generatedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setBreakpoints(args: DebugProtocol.SetBreakpointsArguments, requestSeq: number): void {
|
||||
if (this._sourceMaps && args.source.path) {
|
||||
const argsPath = args.source.path;
|
||||
|
||||
args.source.path = this._sourceMaps.MapPathFromSource(argsPath) || argsPath;
|
||||
args.lines = args.lines.map(line => {
|
||||
const mapped = this._sourceMaps.MapFromSource(argsPath, line, /*column=*/0);
|
||||
return mapped ? mapped.line : line;
|
||||
});
|
||||
|
||||
this._requestSeqToSetBreakpointsArgs.set(requestSeq, JSON.parse(JSON.stringify(args)));
|
||||
}
|
||||
}
|
||||
|
||||
public setBreakpointsResponse(response: SetBreakpointsResponseBody, requestSeq: number): void {
|
||||
if (this._sourceMaps && this._requestSeqToSetBreakpointsArgs.has(requestSeq)) {
|
||||
const args = this._requestSeqToSetBreakpointsArgs.get(requestSeq);
|
||||
response.breakpoints.forEach(bp => {
|
||||
const mapped = this._sourceMaps.MapToSource(args.source.path, bp.line, (<any>bp).column);
|
||||
delete (<any>bp).column;
|
||||
if (mapped) {
|
||||
bp.line = mapped.line;
|
||||
}
|
||||
|
||||
this._requestSeqToSetBreakpointsArgs.delete(requestSeq);
|
||||
});
|
||||
} else {
|
||||
// Cleanup column, which is passed in here in case it's needed for sourcemaps, but isn't actually
|
||||
// part of the DebugProtocol
|
||||
response.breakpoints.forEach(bp => {
|
||||
delete (<any>bp).column;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public stackTraceResponse(response: StackTraceResponseBody): void {
|
||||
if (this._sourceMaps) {
|
||||
response.stackFrames.forEach(stackFrame => {
|
||||
const mapped = this._sourceMaps.MapToSource(stackFrame.source.path, stackFrame.line, stackFrame.column);
|
||||
if (mapped) {
|
||||
stackFrame.source.path = mapped.path;
|
||||
stackFrame.line = mapped.line;
|
||||
stackFrame.column = mapped.column;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,13 +44,16 @@ gulp.task('default', ['build']);
|
|||
|
||||
function test() {
|
||||
return gulp.src('out/test/**/*.test.js', { read: false })
|
||||
.pipe(mocha())
|
||||
.on('error', function() { });
|
||||
.pipe(mocha({ ui: 'tdd' }))
|
||||
.on('error', function(e) {
|
||||
log(e ? e.toString() : 'error in test task!');
|
||||
this.emit('end');
|
||||
});
|
||||
}
|
||||
|
||||
gulp.task('build-test', ['build'], test);
|
||||
gulp.task('test', test);
|
||||
|
||||
gulp.task('watch-build-test', ['build', 'build-test'], function(cb) {
|
||||
gulp.task('watch-build-test', ['build', 'build-test'], function() {
|
||||
return gulp.watch(sources, ['build', 'build-test']);
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"gulp-typescript": "^2.8.0",
|
||||
"gulp-util": "^3.0.5",
|
||||
"mocha": "^2.3.3",
|
||||
"mockery": "^1.4.0",
|
||||
"tsd": "^0.6.3",
|
||||
"typescript": "^1.6.2"
|
||||
},
|
||||
|
|
|
@ -14,13 +14,13 @@ function createTransformer(clientLinesStartAt1: boolean, targetLinesStartAt1: bo
|
|||
return transformer;
|
||||
}
|
||||
|
||||
describe('LineNumberTransformer', () => {
|
||||
suite('LineNumberTransformer', () => {
|
||||
const c0t0Transformer = createTransformer(false, false);
|
||||
const c0t1Transformer = createTransformer(false, true);
|
||||
const c1t0Transformer = createTransformer(true, false);
|
||||
const c1t1Transformer = createTransformer(true, true);
|
||||
|
||||
describe('setBreakpoints()', () => {
|
||||
suite('setBreakpoints()', () => {
|
||||
function getArgs(lines: number[]): DebugProtocol.SetBreakpointsArguments {
|
||||
return {
|
||||
source: { path: "test/path" },
|
||||
|
@ -34,7 +34,7 @@ describe('LineNumberTransformer', () => {
|
|||
assert.deepEqual(args, getArgs(tLines));
|
||||
}
|
||||
|
||||
it('fixes args.lines', () => {
|
||||
test('fixes args.lines', () => {
|
||||
testSetBreakpoints(c0t0Transformer, [0, 1, 2]);
|
||||
testSetBreakpoints(c0t1Transformer, [0, 1, 2], [1, 2, 3]);
|
||||
testSetBreakpoints(c1t0Transformer, [1, 2, 3], [0, 1, 2]);
|
||||
|
@ -42,7 +42,7 @@ describe('LineNumberTransformer', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('setBreakpointsResponse()', () => {
|
||||
suite('setBreakpointsResponse()', () => {
|
||||
function getResponse(lines: number[]): SetBreakpointsResponseBody {
|
||||
return {
|
||||
breakpoints: lines.map(line => ({ verified: true, line: line }))
|
||||
|
@ -55,7 +55,7 @@ describe('LineNumberTransformer', () => {
|
|||
assert.deepEqual(response, getResponse(cLines));
|
||||
}
|
||||
|
||||
it('fixes the breakpoints\' lines', () => {
|
||||
test('fixes the breakpoints\' lines', () => {
|
||||
testSetBreakpointsResponse(c0t0Transformer, [0, 1, 2]);
|
||||
testSetBreakpointsResponse(c0t1Transformer, [1, 2, 3], [0, 1, 2]);
|
||||
testSetBreakpointsResponse(c1t0Transformer, [0, 1, 2], [1, 2, 3]);
|
||||
|
@ -63,7 +63,7 @@ describe('LineNumberTransformer', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('stackTraceResponse', () => {
|
||||
suite('stackTraceResponse()', () => {
|
||||
function getResponse(lines: number[]): StackTraceResponseBody {
|
||||
return {
|
||||
stackFrames: lines.map(line => ({ id: 0, name: '', line, column: 0 }))
|
||||
|
@ -76,11 +76,11 @@ describe('LineNumberTransformer', () => {
|
|||
assert.deepEqual(response, getResponse(cLines));
|
||||
}
|
||||
|
||||
it('fixes the stackFrames\' lines', () => {
|
||||
test('fixes the stackFrames\' lines', () => {
|
||||
testStackTraceResponse(c0t0Transformer, [0, 1, 2]);
|
||||
testStackTraceResponse(c0t1Transformer, [1, 2, 3], [0, 1, 2]);
|
||||
testStackTraceResponse(c1t0Transformer, [0, 1, 2], [1, 2, 3]);
|
||||
testStackTraceResponse(c1t1Transformer, [1, 2, 3]);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,199 @@
|
|||
/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import assert = require('assert');
|
||||
import mockery = require('mockery');
|
||||
import { ISourceMaps, MappingResult } from '../../../adapter/sourceMaps/sourceMaps';
|
||||
|
||||
const MODULE_UNDER_TEST = '../../../adapter/sourceMaps/sourceMapTransformer';
|
||||
const AUTHORED_PATH = 'authored.ts';
|
||||
const RUNTIME_PATH = 'runtime.js';
|
||||
const AUTHORED_LINES = [1, 2, 3];
|
||||
const RUNTIME_LINES = [2, 5, 8];
|
||||
|
||||
suite('SourceMapTransformer', () => {
|
||||
let transformer: IDebugTransformer;
|
||||
let transformerSMDisabled: IDebugTransformer;
|
||||
|
||||
setup(() => {
|
||||
// Set up mockery with SourceMaps mock
|
||||
mockery.enable();
|
||||
mockery.registerMock('./sourceMaps', { SourceMaps: MockSourceMaps });
|
||||
mockery.registerAllowable(MODULE_UNDER_TEST);
|
||||
|
||||
// Grab the test class with mock injected, instantiate with and without sourcemaps enabled
|
||||
let SourceMapTransformer = require(MODULE_UNDER_TEST).SourceMapTransformer;
|
||||
transformer = new SourceMapTransformer();
|
||||
transformer.initialize(<IInitializeRequestArgs><any>{
|
||||
sourceMaps: true,
|
||||
generatedCodeDirectory: 'test'
|
||||
});
|
||||
|
||||
transformerSMDisabled = new SourceMapTransformer();
|
||||
transformerSMDisabled.initialize(<IInitializeRequestArgs><any>{
|
||||
sourceMaps: false,
|
||||
generatedCodeDirectory: 'test'
|
||||
});
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
mockery.deregisterAll();
|
||||
mockery.disable();
|
||||
transformer = null;
|
||||
transformerSMDisabled = null;
|
||||
});
|
||||
|
||||
suite('launch()', () => {
|
||||
test('modifies args.path when present', () => {
|
||||
const args = <ILaunchRequestArgs>{ workingDirectory: 'C:/code', program: 'authored.ts' };
|
||||
const expected = <ILaunchRequestArgs>{ workingDirectory: 'C:/code', program: 'runtime.js' };
|
||||
|
||||
transformer.launch(args);
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
|
||||
test('doesn\'t do anything when args.path is missing, e.g. args.url was set', () => {
|
||||
const args = <ILaunchRequestArgs>{ workingDirectory: 'C:/code' };
|
||||
const expected = <ILaunchRequestArgs>{ workingDirectory: 'C:/code' };
|
||||
|
||||
transformer.launch(args);
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
|
||||
test('doesn\'t do anything when sourcemaps are disabled', () => {
|
||||
const args = <ILaunchRequestArgs>{ workingDirectory: 'C:/code' };
|
||||
const expected = <ILaunchRequestArgs>{ workingDirectory: 'C:/code' };
|
||||
|
||||
transformerSMDisabled.launch(args);
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
});
|
||||
|
||||
suite('setBreakpoints()', () => {
|
||||
function createArgs(path: string, lines:number[]): DebugProtocol.SetBreakpointsArguments {
|
||||
return {
|
||||
source: { path },
|
||||
lines
|
||||
};
|
||||
}
|
||||
|
||||
test('modifies the source and lines', () => {
|
||||
const args = createArgs(AUTHORED_PATH, AUTHORED_LINES);
|
||||
const expected = createArgs(RUNTIME_PATH, RUNTIME_LINES);
|
||||
|
||||
transformer.setBreakpoints(args);
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
|
||||
test('doesn\'t do anything when sourcemaps are disabled', () => {
|
||||
const args = createArgs(RUNTIME_PATH, RUNTIME_LINES);
|
||||
const expected = createArgs(RUNTIME_PATH, RUNTIME_LINES);
|
||||
|
||||
transformerSMDisabled.setBreakpoints(args);
|
||||
assert.deepEqual(args, expected);
|
||||
});
|
||||
|
||||
suite('setBreakpointsResponse()', () => {
|
||||
function getResponseBody(lines: number[], column?: number): SetBreakpointsResponseBody {
|
||||
return {
|
||||
breakpoints: lines.map(line => {
|
||||
const bp = { line, verified: true };
|
||||
if (column !== undefined) {
|
||||
(<any>bp).column = column;
|
||||
}
|
||||
|
||||
return bp;
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
test('modifies the response source and lines', () => {
|
||||
const response = getResponseBody(RUNTIME_LINES, /*column=*/0);
|
||||
const expected = getResponseBody(AUTHORED_LINES);
|
||||
|
||||
transformer.setBreakpoints(<DebugProtocol.SetBreakpointsArguments>{
|
||||
source: { path: AUTHORED_PATH },
|
||||
lines: AUTHORED_LINES
|
||||
});
|
||||
transformer.setBreakpointsResponse(response);
|
||||
assert.deepEqual(response, expected);
|
||||
});
|
||||
|
||||
test('doesn\'t do anything when sourcemaps are disabled except remove the column', () => {
|
||||
const response = getResponseBody(RUNTIME_LINES, /*column=*/0);
|
||||
const expected = getResponseBody(RUNTIME_LINES);
|
||||
|
||||
transformerSMDisabled.setBreakpoints(<DebugProtocol.SetBreakpointsArguments>{
|
||||
source: { path: RUNTIME_PATH },
|
||||
lines: RUNTIME_LINES
|
||||
});
|
||||
transformerSMDisabled.setBreakpointsResponse(response);
|
||||
assert.deepEqual(response, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('stackTraceResponse', () => {
|
||||
function getResponseBody(path: string, lines: number[]): StackTraceResponseBody {
|
||||
return {
|
||||
stackFrames: lines.map((line, i) => ({
|
||||
id: i,
|
||||
name: 'line ' + i,
|
||||
line,
|
||||
column: 0,
|
||||
source: { path }
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
test('modifies the response stackFrames', () => {
|
||||
const response = getResponseBody(RUNTIME_PATH, RUNTIME_LINES);
|
||||
const expected = getResponseBody(AUTHORED_PATH, AUTHORED_LINES);
|
||||
|
||||
transformer.stackTraceResponse(response);
|
||||
assert.deepEqual(response, expected);
|
||||
});
|
||||
|
||||
test('does nothing when there are no sourcemaps', () => {
|
||||
const response = getResponseBody(RUNTIME_PATH, RUNTIME_LINES);
|
||||
const expected = getResponseBody(RUNTIME_PATH, RUNTIME_LINES);
|
||||
|
||||
transformerSMDisabled.stackTraceResponse(response);
|
||||
assert.deepEqual(response, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class MockSourceMaps implements ISourceMaps {
|
||||
constructor(private generatedCodeDirectory: string) { }
|
||||
|
||||
public MapPathFromSource(path: string): string {
|
||||
assert.equal(path, AUTHORED_PATH);
|
||||
return RUNTIME_PATH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map location in source language to location in generated code.
|
||||
* line and column are 0 based.
|
||||
*/
|
||||
public MapFromSource(path: string, line: number, column: number): MappingResult {
|
||||
assert.equal(path, AUTHORED_PATH);
|
||||
assert.equal(column, 0);
|
||||
|
||||
const mappedLine = RUNTIME_LINES[AUTHORED_LINES.indexOf(line)];
|
||||
return { path: RUNTIME_PATH, line: mappedLine, column: 0 };
|
||||
}
|
||||
|
||||
/*
|
||||
* Map location in generated code to location in source language.
|
||||
* line and column are 0 based.
|
||||
*/
|
||||
public MapToSource(path: string, line: number, column: number): MappingResult {
|
||||
assert.equal(path, RUNTIME_PATH);
|
||||
assert.equal(column, 0);
|
||||
|
||||
const mappedLine = AUTHORED_LINES[RUNTIME_LINES.indexOf(line)];
|
||||
return { path: AUTHORED_PATH, line: mappedLine, column: 0 };
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
"runtimeArgs": ["http://localhost:8080/out/client/index.html?2"],
|
||||
"cwd": ".",
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": false,
|
||||
"sourceMaps": true,
|
||||
"outDir": "out"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -6,27 +6,5 @@
|
|||
"target": "ES5",
|
||||
"sourceMap": true,
|
||||
"outDir": "out"
|
||||
},
|
||||
"files": [
|
||||
"adapter/adapterProxy.ts",
|
||||
"adapter/lineNumberTransformer.ts",
|
||||
"webkit/openDebugWebKit.ts",
|
||||
"webkit/pathUtilities.ts",
|
||||
"webkit/sourceMaps.ts",
|
||||
"webkit/utilities.ts",
|
||||
"webkit/webKitConnection.ts",
|
||||
"webkit/webKitDebugAdapter.ts",
|
||||
"webkit/webKitDebugSession.ts",
|
||||
"webkit/webKitProtocol.d.ts",
|
||||
"webkit/webKitAdapterInterfaces.d.ts",
|
||||
"common/debugProtocol.d.ts",
|
||||
"common/debugSession.ts",
|
||||
"common/handles.ts",
|
||||
"common/v8Protocol.ts",
|
||||
"typings/es6-collections/es6-collections.d.ts",
|
||||
"typings/es6-promise/es6-promise.d.ts",
|
||||
"typings/node/node.d.ts",
|
||||
"typings/source-map/source-map.d.ts",
|
||||
"typings/ws/ws.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Type definitions for mockery 1.4.0
|
||||
// Project: https://github.com/mfncooper/mockery
|
||||
// Definitions by: jt000 <https://github.com/jt000>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
declare module "mockery" {
|
||||
|
||||
interface MockeryEnableArgs {
|
||||
useCleanCache?: boolean;
|
||||
warnOnReplace?: boolean;
|
||||
warnOnUnregistered?: boolean;
|
||||
}
|
||||
|
||||
export function enable(args?: MockeryEnableArgs): void;
|
||||
export function disable(): void;
|
||||
|
||||
export function registerMock(name: string, mock: any): void;
|
||||
export function deregisterMock(name: string): void;
|
||||
|
||||
export function registerSubstitute(name: string, substitute: string): void;
|
||||
export function deregisterSubstitute(name: string): void;
|
||||
|
||||
export function registerAllowable(name: string, unhook?: boolean): void;
|
||||
export function deregisterAllowable(name: string): void;
|
||||
|
||||
export function registerAllowables(names: string[]): void;
|
||||
export function deregisterAllowables(names: string[]): void;
|
||||
|
||||
export function deregisterAll(): void;
|
||||
export function resetCache(): void;
|
||||
export function warnOnUnregistered(value: boolean): void;
|
||||
export function warnOnReplace(value: boolean): void;
|
||||
}
|
|
@ -77,23 +77,23 @@ interface IDebugAdapter {
|
|||
|
||||
declare type PromiseOrNot<T> = T | Promise<T>;
|
||||
interface IDebugTransformer {
|
||||
initialize?(args: IInitializeRequestArgs): PromiseOrNot<void>;
|
||||
launch?(args: ILaunchRequestArgs): PromiseOrNot<void>;
|
||||
attach?(args: IAttachRequestArgs): PromiseOrNot<void>;
|
||||
setBreakpoints?(args: DebugProtocol.SetBreakpointsArguments): PromiseOrNot<void>;
|
||||
setExceptionBreakpoints?(args: DebugProtocol.SetExceptionBreakpointsArguments): PromiseOrNot<void>;
|
||||
initialize?(args: IInitializeRequestArgs, requestSeq?: number): PromiseOrNot<void>;
|
||||
launch?(args: ILaunchRequestArgs, requestSeq?: number): PromiseOrNot<void>;
|
||||
attach?(args: IAttachRequestArgs, requestSeq?: number): PromiseOrNot<void>;
|
||||
setBreakpoints?(args: DebugProtocol.SetBreakpointsArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
setExceptionBreakpoints?(args: DebugProtocol.SetExceptionBreakpointsArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
|
||||
stackTrace?(args: DebugProtocol.StackTraceArguments): PromiseOrNot<void>;
|
||||
scopes?(args: DebugProtocol.ScopesArguments): PromiseOrNot<void>;
|
||||
variables?(args: DebugProtocol.VariablesArguments): PromiseOrNot<void>;
|
||||
source?(args: DebugProtocol.SourceArguments): PromiseOrNot<void>;
|
||||
evaluate?(args: DebugProtocol.EvaluateArguments): PromiseOrNot<void>;
|
||||
stackTrace?(args: DebugProtocol.StackTraceArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
scopes?(args: DebugProtocol.ScopesArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
variables?(args: DebugProtocol.VariablesArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
source?(args: DebugProtocol.SourceArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
evaluate?(args: DebugProtocol.EvaluateArguments, requestSeq?: number): PromiseOrNot<void>;
|
||||
|
||||
setBreakpointsResponse?(response: SetBreakpointsResponseBody): PromiseOrNot<void>;
|
||||
stackTraceResponse?(response: StackTraceResponseBody): PromiseOrNot<void>;
|
||||
scopesResponse?(response: ScopesResponseBody): PromiseOrNot<void>;
|
||||
variablesResponse?(response: VariablesResponseBody): PromiseOrNot<void>;
|
||||
sourceResponse?(response: SourceResponseBody): PromiseOrNot<void>;
|
||||
threadsResponse?(response: ThreadsResponseBody): PromiseOrNot<void>;
|
||||
evaluateResponse?(response: EvaluateResponseBody): PromiseOrNot<void>;
|
||||
setBreakpointsResponse?(response: SetBreakpointsResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
stackTraceResponse?(response: StackTraceResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
scopesResponse?(response: ScopesResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
variablesResponse?(response: VariablesResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
sourceResponse?(response: SourceResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
threadsResponse?(response: ThreadsResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
evaluateResponse?(response: EvaluateResponseBody, requestSeq?: number): PromiseOrNot<void>;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import {DebugSession, StoppedEvent, InitializedEvent, TerminatedEvent} from '../
|
|||
import {Handles} from '../common/handles';
|
||||
import {WebKitConnection} from './webKitConnection';
|
||||
import Utilities = require('./utilities');
|
||||
import {ISourceMaps, SourceMaps} from './sourceMaps';
|
||||
|
||||
import {spawn, ChildProcess} from 'child_process';
|
||||
import nodeUrl = require('url');
|
||||
|
@ -32,8 +31,6 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
private _currentStack: WebKitProtocol.Debugger.CallFrame[];
|
||||
private _pendingBreakpointsByUrl: Map<string, IPendingBreakpoint>;
|
||||
private _committedBreakpointsByScriptId: Map<WebKitProtocol.Debugger.ScriptId, WebKitProtocol.Debugger.BreakpointId[]>;
|
||||
private _sourceMaps: ISourceMaps;
|
||||
private _generatedCodeDirectory: string;
|
||||
private _overlayHelper: Utilities.DebounceHelper;
|
||||
|
||||
private _chromeProc: ChildProcess;
|
||||
|
@ -75,11 +72,6 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
|
||||
public initialize(args: IInitializeRequestArgs): Promise<void> {
|
||||
this._clientLinesStartAt1 = args.linesStartAt1;
|
||||
if (args.sourceMaps) {
|
||||
this._sourceMaps = new SourceMaps(args.generatedCodeDirectory);
|
||||
this._generatedCodeDirectory = args.generatedCodeDirectory;
|
||||
}
|
||||
|
||||
return Promise.resolve<void>();
|
||||
}
|
||||
|
||||
|
@ -98,17 +90,11 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
}
|
||||
|
||||
if (args.program) {
|
||||
// Can html files be sourcemapped? May as well try.
|
||||
if (this._sourceMaps) {
|
||||
const generatedPath = this._sourceMaps.MapPathFromSource(args.program);
|
||||
if (generatedPath) {
|
||||
args.program = generatedPath;
|
||||
}
|
||||
}
|
||||
|
||||
chromeArgs.push(args.program);
|
||||
} else if (args.url) {
|
||||
chromeArgs.push(args.url);
|
||||
} else {
|
||||
// TODO fail
|
||||
}
|
||||
|
||||
if (args.arguments) {
|
||||
|
@ -234,9 +220,7 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
private _setAllBreakpoints(args: DebugProtocol.SetBreakpointsArguments): Promise<SetBreakpointsResponseBody> {
|
||||
let targetScript: WebKitProtocol.Debugger.Script;
|
||||
if (args.source.path) {
|
||||
const path = (this._sourceMaps && this._sourceMaps.MapPathFromSource(args.source.path)) || args.source.path;
|
||||
const canPath = canonicalizeUrl(path);
|
||||
targetScript = this._scriptsByUrl.get(canPath);
|
||||
targetScript = this._scriptsByUrl.get(canonicalizeUrl(args.source.path));
|
||||
} else if (args.source.sourceReference) {
|
||||
targetScript = this._scriptsById.get(sourceReferenceToScriptId(args.source.sourceReference));
|
||||
} else if (args.source.name) {
|
||||
|
@ -263,15 +247,6 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
private _addBreakpoints(sourcePath: string, scriptId: WebKitProtocol.Debugger.ScriptId, lines: number[]): Promise<WebKitProtocol.Debugger.SetBreakpointResponse[]> {
|
||||
// Adjust lines for sourcemaps, call setBreakpoint for all breakpoints in the script simultaneously
|
||||
const responsePs = lines
|
||||
.map(debuggerLine => {
|
||||
// Sourcemap lines
|
||||
if (this._sourceMaps) {
|
||||
const mapped = this._sourceMaps.MapFromSource(sourcePath, debuggerLine, /*column=*/0);
|
||||
return mapped ? mapped.line : debuggerLine;
|
||||
} else {
|
||||
return debuggerLine;
|
||||
}
|
||||
})
|
||||
.map(lineNumber => this._webKitConnection.debugger_setBreakpoint({ scriptId: scriptId, lineNumber }));
|
||||
|
||||
// Join all setBreakpoint requests to a single promise
|
||||
|
@ -290,18 +265,11 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
return successfulResponses
|
||||
.map(response => {
|
||||
let line = response.result.actualLocation.lineNumber;
|
||||
if (this._sourceMaps) {
|
||||
const clientUrl = this.webkitUrlToClientUrl(script.url);
|
||||
const mapped = this._sourceMaps.MapToSource(clientUrl, response.result.actualLocation.lineNumber, response.result.actualLocation.columnNumber);
|
||||
if (mapped) {
|
||||
line = mapped.line;
|
||||
}
|
||||
}
|
||||
|
||||
return <DebugProtocol.Breakpoint>{
|
||||
verified: true,
|
||||
line: line
|
||||
}
|
||||
line,
|
||||
column: response.result.actualLocation.columnNumber
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -350,15 +318,8 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
let path = this.webkitUrlToClientUrl(script.url);
|
||||
let line = callFrame.location.lineNumber;
|
||||
let column = callFrame.location.columnNumber;
|
||||
if (this._sourceMaps) {
|
||||
const mapped = this._sourceMaps.MapToSource(path, line, column);
|
||||
if (mapped) {
|
||||
path = mapped.path;
|
||||
line = mapped.line;
|
||||
column = mapped.column;
|
||||
}
|
||||
}
|
||||
|
||||
// Both?
|
||||
const source = <DebugProtocol.Source>{
|
||||
path,
|
||||
sourceReference: scriptIdToSourceReference(script.scriptId)
|
||||
|
@ -398,7 +359,7 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
return { variables };
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve<VariablesResponseBody>();
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,8 +467,7 @@ export class WebKitDebugAdapter implements IDebugAdapter {
|
|||
|
||||
const pathParts = pathName.split('/');
|
||||
while (pathParts.length > 0) {
|
||||
const rootDir = this._sourceMaps ? this._generatedCodeDirectory : this._clientCWD;
|
||||
const clientUrl = path.join(rootDir, pathParts.join('/'));
|
||||
const clientUrl = path.join(this._clientCWD, pathParts.join('/'));
|
||||
if (fs.existsSync(clientUrl)) {
|
||||
return canonicalizeUrl(clientUrl); // path.join will change / to \
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {WebKitDebugAdapter} from './webKitDebugAdapter';
|
|||
|
||||
import {AdapterProxy} from '../adapter/adapterProxy';
|
||||
import {LineNumberTransformer} from '../adapter/lineNumberTransformer';
|
||||
import {SourceMapTransformer} from '../adapter/sourceMaps/sourceMapTransformer';
|
||||
|
||||
export class WebKitDebugSession extends DebugSession {
|
||||
private _adapterProxy: AdapterProxy;
|
||||
|
@ -16,7 +17,10 @@ export class WebKitDebugSession extends DebugSession {
|
|||
super(targetLinesStartAt1, isServer);
|
||||
|
||||
this._adapterProxy = new AdapterProxy(
|
||||
[new LineNumberTransformer(targetLinesStartAt1)],
|
||||
[
|
||||
new LineNumberTransformer(targetLinesStartAt1),
|
||||
new SourceMapTransformer()
|
||||
],
|
||||
new WebKitDebugAdapter(),
|
||||
event => this.sendEvent(event));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче