Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"semver": "5.6.0",
"universal-analytics": "0.4.15",
"uuid": "3.3.2",
"vscode-chrome-debug-core": "6.7.45",
"vscode-chrome-debug-core": "6.7.46",
"vscode-debugadapter": "1.34.0"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions src/debug-adapter/nativeScriptDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from 'path';
import { chromeConnection, ChromeDebugSession } from 'vscode-chrome-debug-core';
import { NativeScriptDebugAdapter } from './nativeScriptDebugAdapter';
import { NativeScriptPathTransformer } from './nativeScriptPathTransformer';
import { NativeScriptSourceMapTransformer } from './nativeScriptSourceMapTransformer';
import { NativeScriptTargetDiscovery } from './nativeScriptTargetDiscovery';

class NSAndroidConnection extends chromeConnection.ChromeConnection {
Expand All @@ -18,4 +19,5 @@ ChromeDebugSession.run(ChromeDebugSession.getSession(
extensionName: 'nativescript-extension',
logFilePath: path.join(os.tmpdir(), 'nativescript-extension.txt'),
pathTransformer: NativeScriptPathTransformer,
sourceMapTransformer: NativeScriptSourceMapTransformer,
}));
35 changes: 33 additions & 2 deletions src/debug-adapter/nativeScriptDebugAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { existsSync, readFileSync } from 'fs';
import * as _ from 'lodash';
import { join } from 'path';
import { ChromeDebugAdapter, IRestartRequestArgs } from 'vscode-chrome-debug-core';
import {
ChromeDebugAdapter,
IRestartRequestArgs,
ISetBreakpointsArgs,
ISetBreakpointsResponseBody,
ITelemetryPropertyCollector,
} from 'vscode-chrome-debug-core';
import { Event, TerminatedEvent } from 'vscode-debugadapter';
import { DebugProtocol } from 'vscode-debugprotocol';
import * as extProtocol from '../common/extensionProtocol';
import { NativeScriptSourceMapTransformer } from './nativeScriptSourceMapTransformer';

const reconnectAfterLiveSyncTimeout = 10 * 1000;

Expand All @@ -14,6 +22,7 @@ export class NativeScriptDebugAdapter extends ChromeDebugAdapter {
private portWaitingResolve: any;
private isDisconnecting: boolean = false;
private isLiveSyncRestart: boolean = false;
private breakPointsCache: { [file: string]: { args: ISetBreakpointsArgs, requestSeq: number, ids: number[] } } = {};

public attach(args: any): Promise<void> {
return this.processRequestAndAttach(args);
Expand Down Expand Up @@ -41,6 +50,27 @@ export class NativeScriptDebugAdapter extends ChromeDebugAdapter {
super.disconnect(args);
}

public async setCachedBreakpointsForScript(script: string): Promise<void> {
const breakPointData = this.breakPointsCache[script];

if (breakPointData) {
await this.setBreakpoints(breakPointData.args, null, breakPointData.requestSeq, breakPointData.ids);
}
}

public async setBreakpoints(
args: ISetBreakpointsArgs,
telemetryPropertyCollector: ITelemetryPropertyCollector,
requestSeq: number,
ids?: number[]): Promise<ISetBreakpointsResponseBody> {

if (args && args.source && args.source.path) {
this.breakPointsCache[args.source.path] = { args: _.cloneDeep(args), requestSeq, ids };
}

return super.setBreakpoints(args, telemetryPropertyCollector, requestSeq, ids);
}

protected async terminateSession(reason: string, disconnectArgs?: DebugProtocol.DisconnectArguments, restart?: IRestartRequestArgs): Promise<void> {
let restartRequestArgs = restart;
let timeoutId;
Expand Down Expand Up @@ -113,6 +143,7 @@ export class NativeScriptDebugAdapter extends ChromeDebugAdapter {
const appDirPath = this.getAppDirPath(transformedArgs.webRoot);

(this.pathTransformer as any).setTransformOptions(args.platform, appDirPath, transformedArgs.webRoot);
(this.sourceMapTransformer as NativeScriptSourceMapTransformer).setDebugAdapter(this);
(ChromeDebugAdapter as any).SET_BREAKPOINTS_TIMEOUT = 20000;

this.isLiveSync = args.watch;
Expand Down Expand Up @@ -145,7 +176,7 @@ export class NativeScriptDebugAdapter extends ChromeDebugAdapter {
}

if (!args.sourceMapPathOverrides) {
args.sourceMapPathOverrides = { };
args.sourceMapPathOverrides = {};
}

if (!args.sourceMapPathOverrides['webpack:///*']) {
Expand Down
22 changes: 15 additions & 7 deletions src/debug-adapter/nativeScriptPathTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ export class NativeScriptPathTransformer extends UrlPathTransformer {
}

const isAndroid = this.targetPlatform === 'android';
const isIOS = this.targetPlatform === 'ios';

if (_.startsWith(scriptUrl, 'mdha:')) {
scriptUrl = _.trimStart(scriptUrl, 'mdha:');
}

if (path.isAbsolute(scriptUrl) && fs.existsSync(scriptUrl)) {
return Promise.resolve(scriptUrl);
return scriptUrl;
}

const filePattern = this.filePatterns[this.targetPlatform];
Expand All @@ -56,20 +57,23 @@ export class NativeScriptPathTransformer extends UrlPathTransformer {
let platformSpecificPath = this.getPlatformSpecificPath(absolutePath);

if (platformSpecificPath) {
return Promise.resolve(platformSpecificPath);
return platformSpecificPath;
}

if (isAndroid) {
// handle files like /data/data/internal/ts_helpers.ts
absolutePath = path.resolve(path.join(this.webRoot, 'platforms', this.targetPlatform.toLowerCase(), 'app', 'src', 'main', 'assets', relativePath));
platformSpecificPath = this.getPlatformSpecificPath(absolutePath);
} else if (isIOS) {
absolutePath = path.resolve(path.join(this.webRoot, 'platforms', this.targetPlatform.toLowerCase(), this.getAppName(this.webRoot), relativePath));
}

if (platformSpecificPath) {
return Promise.resolve(platformSpecificPath);
}
platformSpecificPath = this.getPlatformSpecificPath(absolutePath);

if (platformSpecificPath) {
return platformSpecificPath;
}

return Promise.resolve(scriptUrl);
return scriptUrl;
}

private getPlatformSpecificPath(rawPath: string): string {
Expand All @@ -89,4 +93,8 @@ export class NativeScriptPathTransformer extends UrlPathTransformer {

return null;
}

private getAppName(projectDir: string): string {
return _.filter(projectDir.split(''), (c) => /[a-zA-Z0-9]/.test(c)).join('');
}
}
26 changes: 26 additions & 0 deletions src/debug-adapter/nativeScriptSourceMapTransformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BaseSourceMapTransformer } from 'vscode-chrome-debug-core';
import { NativeScriptDebugAdapter } from './nativeScriptDebugAdapter';

export class NativeScriptSourceMapTransformer extends BaseSourceMapTransformer {
private debugAdapter: NativeScriptDebugAdapter;

constructor(sourceHandles: any) {
super(sourceHandles);
}

public setDebugAdapter(debugAdapter: NativeScriptDebugAdapter): void {
this.debugAdapter = debugAdapter;
}

public async scriptParsed(pathToGenerated: string, sourceMapURL: string): Promise<string[]> {
const scriptParsedResult = await super.scriptParsed(pathToGenerated, sourceMapURL);

if (scriptParsedResult && scriptParsedResult.length) {
for (const script of scriptParsedResult) {
await this.debugAdapter.setCachedBreakpointsForScript(script);
}
}

return scriptParsedResult;
}
}
4 changes: 2 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ export function activate(context: vscode.ExtensionContext) {
const method = service[request.method];
const response = typeof method === 'function' ? service[request.method].call(service, ...request.args) : method;

if (response.then) {
response.then((result) => event.session.customRequest('onExtensionResponse', { requestId: request.id, result }),
if (response && response.then) {
response.then((result) => event.session && event.session.customRequest('onExtensionResponse', { requestId: request.id, result }),
(err: Error) => {
vscode.window.showErrorMessage(err.message);
event.session.customRequest('onExtensionResponse', { requestId: request.id, isError: true, message: err.message });
Expand Down
19 changes: 14 additions & 5 deletions src/tests/nativeScriptDebugAdapter.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const defaultArgsMock: any = {
platform: 'android',
request: 'attach',
stopOnEntry: true,
tnsArgs: [ 'mockArgs'],
tnsArgs: ['mockArgs'],
watch: true,
};

Expand All @@ -37,6 +37,7 @@ describe('NativeScriptDebugAdapter', () => {
let chromeSessionMock: any;
let chromeConnectionMock: any;
let pathTransformerMock: any;
let sourceMapTransformer: any;

beforeEach(() => {
chromeSessionMock = {
Expand All @@ -61,16 +62,24 @@ describe('NativeScriptDebugAdapter', () => {
setTransformOptions: () => ({}),
};

nativeScriptDebugAdapter = new NativeScriptDebugAdapter(
{ chromeConnection: mockConstructor(chromeConnectionMock), pathTransformer: mockConstructor(pathTransformerMock) },
sourceMapTransformer = {
clearTargetContext: () => undefined,
setDebugAdapter: () => undefined,
};

nativeScriptDebugAdapter = new NativeScriptDebugAdapter({
chromeConnection: mockConstructor(chromeConnectionMock),
pathTransformer: mockConstructor(pathTransformerMock),
sourceMapTransformer: mockConstructor(sourceMapTransformer),
},
chromeSessionMock,
);

ChromeDebugAdapter.prototype.attach = () => Promise.resolve();
});

const platforms = [ 'android', 'ios' ];
const launchMethods = [ 'launch', 'attach' ];
const platforms = ['android', 'ios'];
const launchMethods = ['launch', 'attach'];

platforms.forEach((platform) => {
launchMethods.forEach((method) => {
Expand Down