microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
341dba36c6e7ac21203bd58ef861c4803cd85fc0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/debugger/rnDebugSession.ts

240lines · modeblame

6e1bcd36RedMickey6 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as vscode from "vscode";
5import * as path from "path";
6import * as mkdirp from "mkdirp";
2c19da7fRedMickey6 years ago7import { logger } from "vscode-debugadapter";
6e1bcd36RedMickey6 years ago8import { DebugProtocol } from "vscode-debugprotocol";
9import { ProjectVersionHelper } from "../common/projectVersionHelper";
10import { TelemetryHelper } from "../common/telemetryHelper";
11import { MultipleLifetimesAppWorker } from "./appWorker";
a6562589RedMickey6 years ago12import { RnCDPMessageHandler } from "../cdp-proxy/CDPMessageHandlers/rnCDPMessageHandler";
2c19da7fRedMickey6 years ago13import { DebugSessionBase, DebugSessionStatus, IAttachRequestArgs, ILaunchRequestArgs } from "./debugSessionBase";
1bdccb66RedMickey6 years ago14import { JsDebugConfigAdapter } from "./jsDebugConfigAdapter";
5514e287RedMickey6 years ago15import { ErrorHelper } from "../common/error/errorHelper";
16import { InternalErrorCode } from "../common/error/internalErrorCode";
6e1bcd36RedMickey6 years ago17import * as nls from "vscode-nls";
2d8af448Yuri Skorokhodov6 years ago18nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
6e1bcd36RedMickey6 years ago19const localize = nls.loadMessageBundle();
20
2c19da7fRedMickey6 years ago21export class RNDebugSession extends DebugSessionBase {
6e1bcd36RedMickey6 years ago22
4c757eebRedMickey6 years ago23private readonly terminateCommand: string;
f872f4d5RedMickey6 years ago24
e23d1841RedMickey6 years ago25private appWorker: MultipleLifetimesAppWorker | null;
4c757eebRedMickey6 years ago26private nodeSession: vscode.DebugSession | null;
6e491635RedMickey6 years ago27private onDidStartDebugSessionHandler: vscode.Disposable;
28private onDidTerminateDebugSessionHandler: vscode.Disposable;
6e1bcd36RedMickey6 years ago29
2c19da7fRedMickey6 years ago30constructor(session: vscode.DebugSession) {
31super(session);
4c757eebRedMickey6 years ago32
33// constants definition
34this.terminateCommand = "terminate"; // the "terminate" command is sent from the client to the debug adapter in order to give the debuggee a chance for terminating itself
35
36// variables definition
e23d1841RedMickey6 years ago37this.appWorker = null;
38
6e491635RedMickey6 years ago39this.onDidStartDebugSessionHandler = vscode.debug.onDidStartDebugSession(
4c757eebRedMickey6 years ago40this.handleStartDebugSession.bind(this)
41);
42
6e491635RedMickey6 years ago43this.onDidTerminateDebugSessionHandler = vscode.debug.onDidTerminateDebugSession(
4c757eebRedMickey6 years ago44this.handleTerminateDebugSession.bind(this)
45);
6e1bcd36RedMickey6 years ago46}
47
984ca036RedMickey6 years ago48protected async launchRequest(response: DebugProtocol.LaunchResponse, launchArgs: ILaunchRequestArgs, request?: DebugProtocol.Request): Promise<void> {
6e1bcd36RedMickey6 years ago49return new Promise<void>((resolve, reject) => this.initializeSettings(launchArgs)
50.then(() => {
51logger.log("Launching the application");
52logger.verbose(`Launching the application: ${JSON.stringify(launchArgs, null , 2)}`);
53
54this.appLauncher.launch(launchArgs)
55.then(() => {
5514e287RedMickey6 years ago56if (launchArgs.enableDebug) {
57launchArgs.port = launchArgs.port || this.appLauncher.getPackagerPort(launchArgs.cwd);
58this.attachRequest(response, launchArgs).then(() => {
59resolve();
60}).catch((e) => reject(e));
61} else {
62this.sendResponse(response);
6e1bcd36RedMickey6 years ago63resolve();
5514e287RedMickey6 years ago64}
6e1bcd36RedMickey6 years ago65})
66.catch((err) => {
5514e287RedMickey6 years ago67reject(ErrorHelper.getInternalError(InternalErrorCode.ApplicationLaunchFailed, err.message || err));
6e1bcd36RedMickey6 years ago68});
5514e287RedMickey6 years ago69})
70.catch((err) => {
71reject(ErrorHelper.getInternalError(InternalErrorCode.ApplicationLaunchFailed, err.message || err));
72})
73)
74.catch(err => this.showError(err, response));
6e1bcd36RedMickey6 years ago75}
76
984ca036RedMickey6 years ago77protected async attachRequest(response: DebugProtocol.AttachResponse, attachArgs: IAttachRequestArgs, request?: DebugProtocol.Request): Promise<void> {
6e1bcd36RedMickey6 years ago78let extProps = {
79platform: {
80value: attachArgs.platform,
81isPii: false,
82},
83};
84
85this.previousAttachArgs = attachArgs;
86return new Promise<void>((resolve, reject) => this.initializeSettings(attachArgs)
87.then(() => {
88logger.log("Attaching to the application");
89logger.verbose(`Attaching to the application: ${JSON.stringify(attachArgs, null , 2)}`);
341dba36Yuri Skorokhodov5 years ago90return ProjectVersionHelper.getReactNativeVersions(attachArgs.cwd, ProjectVersionHelper.generateAdditionalPackagesToCheckByPlatform(attachArgs));
5514e287RedMickey6 years ago91})
92.then(versions => {
341dba36Yuri Skorokhodov5 years ago93extProps = TelemetryHelper.addPlatformPropertiesToTelemetryProperties(attachArgs, versions, extProps);
94
5514e287RedMickey6 years ago95return TelemetryHelper.generate("attach", extProps, (generator) => {
96attachArgs.port = attachArgs.port || this.appLauncher.getPackagerPort(attachArgs.cwd);
97return this.appLauncher.getRnCdpProxy().stopServer()
98.then(() => this.appLauncher.getRnCdpProxy().initializeServer(new RnCDPMessageHandler(), this.cdpProxyLogLevel))
9fc07913JiglioNero5 years ago99.then(() => this.appLauncher.getPackager().start())
5514e287RedMickey6 years ago100.then(() => {
101logger.log(localize("StartingDebuggerAppWorker", "Starting debugger app worker."));
102
103const sourcesStoragePath = path.join(this.projectRootPath, ".vscode", ".react");
104// Create folder if not exist to avoid problems if
105// RN project root is not a ${workspaceFolder}
106mkdirp.sync(sourcesStoragePath);
107
108// If launch is invoked first time, appWorker is undefined, so create it here
109this.appWorker = new MultipleLifetimesAppWorker(
110attachArgs,
111sourcesStoragePath,
112this.projectRootPath,
113undefined
114);
115this.appLauncher.setAppWorker(this.appWorker);
116
117this.appWorker.on("connected", (port: number) => {
67ffa5b4RedMickey6 years ago118if (this.cancellationTokenSource.token.isCancellationRequested) {
119return this.appWorker?.stop();
120}
121
5514e287RedMickey6 years ago122logger.log(localize("DebuggerWorkerLoadedRuntimeOnPort", "Debugger worker loaded runtime on port {0}", port));
123
124this.appLauncher.getRnCdpProxy().setApplicationTargetPort(port);
125
126if (this.debugSessionStatus === DebugSessionStatus.ConnectionPending) {
127return;
128}
129
130if (this.debugSessionStatus === DebugSessionStatus.FirstConnection) {
131this.debugSessionStatus = DebugSessionStatus.FirstConnectionPending;
132this.establishDebugSession(attachArgs, resolve);
133} else if (this.debugSessionStatus === DebugSessionStatus.ConnectionAllowed) {
134if (this.nodeSession) {
135this.debugSessionStatus = DebugSessionStatus.ConnectionPending;
136this.nodeSession.customRequest(this.terminateCommand);
137}
138}
139});
67ffa5b4RedMickey6 years ago140if (this.cancellationTokenSource.token.isCancellationRequested) {
141return this.appWorker.stop();
142}
5514e287RedMickey6 years ago143return this.appWorker.start();
6e1bcd36RedMickey6 years ago144});
5514e287RedMickey6 years ago145});
146})
147.catch((err) => {
148reject(ErrorHelper.getInternalError(InternalErrorCode.CouldNotAttachToDebugger, err.message || err));
149})
150)
e23d1841RedMickey6 years ago151.catch(err => this.showError(err, response));
6e1bcd36RedMickey6 years ago152}
153
984ca036RedMickey6 years ago154protected async disconnectRequest(response: DebugProtocol.DisconnectResponse, args: DebugProtocol.DisconnectArguments, request?: DebugProtocol.Request): Promise<void> {
6e1bcd36RedMickey6 years ago155// The client is about to disconnect so first we need to stop app worker
156if (this.appWorker) {
157this.appWorker.stop();
158}
159
6e491635RedMickey6 years ago160this.onDidStartDebugSessionHandler.dispose();
161this.onDidTerminateDebugSessionHandler.dispose();
162
6e1bcd36RedMickey6 years ago163super.disconnectRequest(response, args, request);
4c757eebRedMickey6 years ago164}
165
5d47053fRedMickey6 years ago166protected establishDebugSession(attachArgs: IAttachRequestArgs, resolve?: (value?: void | PromiseLike<void> | undefined) => void): void {
1bdccb66RedMickey6 years ago167const attachConfiguration = JsDebugConfigAdapter.createDebuggingConfigForPureRN(
168attachArgs,
169this.appLauncher.getCdpProxyPort(),
170this.session.id
171);
a6562589RedMickey6 years ago172
173vscode.debug.startDebugging(
174this.appLauncher.getWorkspaceFolder(),
1bdccb66RedMickey6 years ago175attachConfiguration,
ebbd64f1RedMickey6 years ago176{
177parentSession: this.session,
178consoleMode: vscode.DebugConsoleMode.MergeWithParent,
179}
a6562589RedMickey6 years ago180)
181.then((childDebugSessionStarted: boolean) => {
182if (childDebugSessionStarted) {
183this.debugSessionStatus = DebugSessionStatus.ConnectionDone;
184this.setConnectionAllowedIfPossible();
185if (resolve) {
186this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
187resolve();
4c757eebRedMickey6 years ago188}
a6562589RedMickey6 years ago189} else {
4c757eebRedMickey6 years ago190this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
191this.setConnectionAllowedIfPossible();
192this.resetFirstConnectionStatus();
a6562589RedMickey6 years ago193throw new Error("Cannot start child debug session");
194}
195},
196err => {
197this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
198this.setConnectionAllowedIfPossible();
4c757eebRedMickey6 years ago199this.resetFirstConnectionStatus();
a6562589RedMickey6 years ago200throw err;
201});
4c757eebRedMickey6 years ago202}
6e1bcd36RedMickey6 years ago203
4c757eebRedMickey6 years ago204private handleStartDebugSession(debugSession: vscode.DebugSession) {
205if (
206debugSession.configuration.rnDebugSessionId === this.session.id
207&& debugSession.type === this.pwaNodeSessionName
208) {
209this.nodeSession = debugSession;
210}
211}
212
213private handleTerminateDebugSession(debugSession: vscode.DebugSession) {
214if (
215debugSession.configuration.rnDebugSessionId === this.session.id
216&& debugSession.type === this.pwaNodeSessionName
217) {
ebbd64f1RedMickey6 years ago218if (this.debugSessionStatus === DebugSessionStatus.ConnectionPending) {
5d47053fRedMickey6 years ago219this.establishDebugSession(this.previousAttachArgs);
ebbd64f1RedMickey6 years ago220} else {
a2ddbba5RedMickey5 years ago221vscode.commands.executeCommand(this.stopCommand, this.session);
ebbd64f1RedMickey6 years ago222}
4c757eebRedMickey6 years ago223}
224}
225
226private setConnectionAllowedIfPossible(): void {
227if (
228this.debugSessionStatus === DebugSessionStatus.ConnectionDone
229|| this.debugSessionStatus === DebugSessionStatus.ConnectionFailed
230) {
231this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
232}
233}
234
235private resetFirstConnectionStatus(): void {
236if (this.debugSessionStatus === DebugSessionStatus.FirstConnectionPending) {
237this.debugSessionStatus = DebugSessionStatus.FirstConnection;
238}
239}
6e1bcd36RedMickey6 years ago240}