microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.5.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/rnDebugSession.ts

336lines · 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";
34472878RedMickey5 years ago13import {
14DebugSessionBase,
15DebugSessionStatus,
16IAttachRequestArgs,
17ILaunchRequestArgs,
18} from "./debugSessionBase";
1bdccb66RedMickey6 years ago19import { JsDebugConfigAdapter } from "./jsDebugConfigAdapter";
5514e287RedMickey6 years ago20import { ErrorHelper } from "../common/error/errorHelper";
21import { InternalErrorCode } from "../common/error/internalErrorCode";
6e1bcd36RedMickey6 years ago22import * as nls from "vscode-nls";
34472878RedMickey5 years ago23nls.config({
24messageFormat: nls.MessageFormat.bundle,
25bundleFormat: nls.BundleFormat.standalone,
26})();
6e1bcd36RedMickey6 years ago27const localize = nls.loadMessageBundle();
28
2c19da7fRedMickey6 years ago29export class RNDebugSession extends DebugSessionBase {
4c757eebRedMickey6 years ago30private readonly terminateCommand: string;
f872f4d5RedMickey6 years ago31
e23d1841RedMickey6 years ago32private appWorker: MultipleLifetimesAppWorker | null;
4c757eebRedMickey6 years ago33private nodeSession: vscode.DebugSession | null;
6e491635RedMickey6 years ago34private onDidStartDebugSessionHandler: vscode.Disposable;
35private onDidTerminateDebugSessionHandler: vscode.Disposable;
6e1bcd36RedMickey6 years ago36
2c19da7fRedMickey6 years ago37constructor(session: vscode.DebugSession) {
38super(session);
4c757eebRedMickey6 years ago39
40// constants definition
41this.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
42
43// variables definition
e23d1841RedMickey6 years ago44this.appWorker = null;
45
6e491635RedMickey6 years ago46this.onDidStartDebugSessionHandler = vscode.debug.onDidStartDebugSession(
34472878RedMickey5 years ago47this.handleStartDebugSession.bind(this),
4c757eebRedMickey6 years ago48);
49
6e491635RedMickey6 years ago50this.onDidTerminateDebugSessionHandler = vscode.debug.onDidTerminateDebugSession(
34472878RedMickey5 years ago51this.handleTerminateDebugSession.bind(this),
4c757eebRedMickey6 years ago52);
6e1bcd36RedMickey6 years ago53}
54
34472878RedMickey5 years ago55protected async launchRequest(
56response: DebugProtocol.LaunchResponse,
57launchArgs: ILaunchRequestArgs,
58// eslint-disable-next-line @typescript-eslint/no-unused-vars
59request?: DebugProtocol.Request,
60): Promise<void> {
61return new Promise<void>((resolve, reject) =>
62this.initializeSettings(launchArgs)
63.then(() => {
64logger.log("Launching the application");
65logger.verbose(
66`Launching the application: ${JSON.stringify(launchArgs, null, 2)}`,
67);
68
69this.appLauncher
70.launch(launchArgs)
71.then(() => {
72if (launchArgs.enableDebug) {
73launchArgs.port =
74launchArgs.port ||
75this.appLauncher.getPackagerPort(launchArgs.cwd);
76this.attachRequest(response, launchArgs)
77.then(() => {
78resolve();
79})
80.catch(e => reject(e));
81} else {
82this.sendResponse(response);
5514e287RedMickey6 years ago83resolve();
34472878RedMickey5 years ago84}
85})
86.catch(err => {
87reject(
88ErrorHelper.getInternalError(
89InternalErrorCode.ApplicationLaunchFailed,
90err.message || err,
91),
92);
93});
94})
95.catch(err => {
96reject(
97ErrorHelper.getInternalError(
98InternalErrorCode.ApplicationLaunchFailed,
99err.message || err,
100),
101);
102}),
103).catch(err => this.showError(err, response));
6e1bcd36RedMickey6 years ago104}
105
34472878RedMickey5 years ago106protected async attachRequest(
107response: DebugProtocol.AttachResponse,
108attachArgs: IAttachRequestArgs,
109// eslint-disable-next-line @typescript-eslint/no-unused-vars
110request?: DebugProtocol.Request,
111): Promise<void> {
6e1bcd36RedMickey6 years ago112let extProps = {
113platform: {
114value: attachArgs.platform,
115isPii: false,
116},
117};
118
119this.previousAttachArgs = attachArgs;
34472878RedMickey5 years ago120return new Promise<void>((resolve, reject) =>
121this.initializeSettings(attachArgs)
122.then(() => {
123logger.log("Attaching to the application");
124logger.verbose(
125`Attaching to the application: ${JSON.stringify(attachArgs, null, 2)}`,
126);
127return ProjectVersionHelper.getReactNativeVersions(
128attachArgs.cwd,
129ProjectVersionHelper.generateAdditionalPackagesToCheckByPlatform(
130attachArgs,
131),
132);
133})
134.then(versions => {
135extProps = TelemetryHelper.addPlatformPropertiesToTelemetryProperties(
136attachArgs,
137versions,
138extProps,
139);
140
141// eslint-disable-next-line @typescript-eslint/no-unused-vars
142return TelemetryHelper.generate("attach", extProps, generator => {
143attachArgs.port =
144attachArgs.port || this.appLauncher.getPackagerPort(attachArgs.cwd);
145return this.appLauncher
146.getRnCdpProxy()
147.stopServer()
148.then(() =>
149this.appLauncher
150.getRnCdpProxy()
151.initializeServer(
152new RnCDPMessageHandler(),
153this.cdpProxyLogLevel,
154),
155)
156.then(() => this.appLauncher.getPackager().start())
157.then(() => {
158logger.log(
159localize(
160"StartingDebuggerAppWorker",
161"Starting debugger app worker.",
162),
5514e287RedMickey6 years ago163);
164
34472878RedMickey5 years ago165const sourcesStoragePath = path.join(
166this.projectRootPath,
167".vscode",
168".react",
169);
170// Create folder if not exist to avoid problems if
171// RN project root is not a ${workspaceFolder}
172mkdirp.sync(sourcesStoragePath);
173
174// If launch is invoked first time, appWorker is undefined, so create it here
175this.appWorker = new MultipleLifetimesAppWorker(
176attachArgs,
177sourcesStoragePath,
178this.projectRootPath,
5940f996RedMickey5 years ago179this.cancellationTokenSource.token,
34472878RedMickey5 years ago180undefined,
181);
182this.appLauncher.setAppWorker(this.appWorker);
67ffa5b4RedMickey5 years ago183
34472878RedMickey5 years ago184this.appWorker.on("connected", (port: number) => {
185if (
186this.cancellationTokenSource.token.isCancellationRequested
187) {
188return this.appWorker?.stop();
189}
5514e287RedMickey6 years ago190
34472878RedMickey5 years ago191logger.log(
192localize(
193"DebuggerWorkerLoadedRuntimeOnPort",
194"Debugger worker loaded runtime on port {0}",
195port,
196),
197);
5514e287RedMickey6 years ago198
34472878RedMickey5 years ago199this.appLauncher.getRnCdpProxy().setApplicationTargetPort(port);
200
201if (
202this.debugSessionStatus ===
203DebugSessionStatus.ConnectionPending
204) {
205return;
206}
5514e287RedMickey6 years ago207
34472878RedMickey5 years ago208if (
209this.debugSessionStatus ===
210DebugSessionStatus.FirstConnection
211) {
212this.debugSessionStatus =
213DebugSessionStatus.FirstConnectionPending;
214this.establishDebugSession(attachArgs, resolve);
215} else if (
216this.debugSessionStatus ===
217DebugSessionStatus.ConnectionAllowed
218) {
219if (this.nodeSession) {
220this.debugSessionStatus =
221DebugSessionStatus.ConnectionPending;
222this.nodeSession.customRequest(this.terminateCommand);
223}
5514e287RedMickey6 years ago224}
34472878RedMickey5 years ago225});
226if (this.cancellationTokenSource.token.isCancellationRequested) {
227return this.appWorker.stop();
5514e287RedMickey6 years ago228}
34472878RedMickey5 years ago229return this.appWorker.start();
5514e287RedMickey6 years ago230});
34472878RedMickey5 years ago231});
232})
233.catch(err => {
234reject(
235ErrorHelper.getInternalError(
236InternalErrorCode.CouldNotAttachToDebugger,
237err.message || err,
238),
239);
240}),
241).catch(err => this.showError(err, response));
6e1bcd36RedMickey6 years ago242}
243
34472878RedMickey5 years ago244protected async disconnectRequest(
245response: DebugProtocol.DisconnectResponse,
246args: DebugProtocol.DisconnectArguments,
247request?: DebugProtocol.Request,
248): Promise<void> {
6e1bcd36RedMickey6 years ago249// The client is about to disconnect so first we need to stop app worker
250if (this.appWorker) {
251this.appWorker.stop();
252}
253
6e491635RedMickey6 years ago254this.onDidStartDebugSessionHandler.dispose();
255this.onDidTerminateDebugSessionHandler.dispose();
256
6e1bcd36RedMickey6 years ago257super.disconnectRequest(response, args, request);
4c757eebRedMickey6 years ago258}
259
34472878RedMickey5 years ago260protected establishDebugSession(
261attachArgs: IAttachRequestArgs,
262resolve?: (value?: void | PromiseLike<void> | undefined) => void,
263): void {
1bdccb66RedMickey6 years ago264const attachConfiguration = JsDebugConfigAdapter.createDebuggingConfigForPureRN(
265attachArgs,
266this.appLauncher.getCdpProxyPort(),
34472878RedMickey5 years ago267this.session.id,
1bdccb66RedMickey6 years ago268);
a6562589RedMickey6 years ago269
34472878RedMickey5 years ago270vscode.debug
271.startDebugging(this.appLauncher.getWorkspaceFolder(), attachConfiguration, {
ebbd64f1RedMickey6 years ago272parentSession: this.session,
273consoleMode: vscode.DebugConsoleMode.MergeWithParent,
34472878RedMickey5 years ago274})
275.then(
276(childDebugSessionStarted: boolean) => {
277if (childDebugSessionStarted) {
278this.debugSessionStatus = DebugSessionStatus.ConnectionDone;
279this.setConnectionAllowedIfPossible();
280if (resolve) {
281this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
282resolve();
283}
284} else {
285this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
286this.setConnectionAllowedIfPossible();
287this.resetFirstConnectionStatus();
288throw new Error("Cannot start child debug session");
289}
290},
291err => {
292this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
293this.setConnectionAllowedIfPossible();
294this.resetFirstConnectionStatus();
295throw err;
296},
297);
4c757eebRedMickey6 years ago298}
6e1bcd36RedMickey6 years ago299
4c757eebRedMickey6 years ago300private handleStartDebugSession(debugSession: vscode.DebugSession) {
301if (
34472878RedMickey5 years ago302debugSession.configuration.rnDebugSessionId === this.session.id &&
303debugSession.type === this.pwaNodeSessionName
4c757eebRedMickey6 years ago304) {
305this.nodeSession = debugSession;
306}
307}
308
309private handleTerminateDebugSession(debugSession: vscode.DebugSession) {
310if (
34472878RedMickey5 years ago311debugSession.configuration.rnDebugSessionId === this.session.id &&
312debugSession.type === this.pwaNodeSessionName
4c757eebRedMickey6 years ago313) {
ebbd64f1RedMickey6 years ago314if (this.debugSessionStatus === DebugSessionStatus.ConnectionPending) {
5d47053fRedMickey6 years ago315this.establishDebugSession(this.previousAttachArgs);
ebbd64f1RedMickey6 years ago316} else {
a2ddbba5RedMickey5 years ago317vscode.commands.executeCommand(this.stopCommand, this.session);
ebbd64f1RedMickey6 years ago318}
4c757eebRedMickey6 years ago319}
320}
321
322private setConnectionAllowedIfPossible(): void {
323if (
34472878RedMickey5 years ago324this.debugSessionStatus === DebugSessionStatus.ConnectionDone ||
325this.debugSessionStatus === DebugSessionStatus.ConnectionFailed
4c757eebRedMickey6 years ago326) {
327this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
328}
329}
330
331private resetFirstConnectionStatus(): void {
332if (this.debugSessionStatus === DebugSessionStatus.FirstConnectionPending) {
333this.debugSessionStatus = DebugSessionStatus.FirstConnection;
334}
335}
6e1bcd36RedMickey6 years ago336}