microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.12.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/rnDebugSession.ts

312lines · 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 path from "path";
09f6024fHeniker4 years ago5import * as vscode from "vscode";
6e1bcd36RedMickey6 years ago6import * as mkdirp from "mkdirp";
623be8a6Ezio Li2 years ago7import { logger } from "@vscode/debugadapter";
6e1bcd36RedMickey6 years ago8import { DebugProtocol } from "vscode-debugprotocol";
09f6024fHeniker4 years ago9import * as nls from "vscode-nls";
6e1bcd36RedMickey6 years ago10import { ProjectVersionHelper } from "../common/projectVersionHelper";
11import { TelemetryHelper } from "../common/telemetryHelper";
a6562589RedMickey6 years ago12import { RnCDPMessageHandler } from "../cdp-proxy/CDPMessageHandlers/rnCDPMessageHandler";
09f6024fHeniker4 years ago13import { ErrorHelper } from "../common/error/errorHelper";
14import { InternalErrorCode } from "../common/error/internalErrorCode";
88c519c3Ezio Li2 years ago15import { ReactNativeProjectHelper } from "../common/reactNativeProjectHelper";
d80f1733Ezio Li2 years ago16import { ExponentHelper } from "../extension/exponent/exponentHelper";
09f6024fHeniker4 years ago17import { MultipleLifetimesAppWorker } from "./appWorker";
34472878RedMickey5 years ago18import {
19DebugSessionBase,
20DebugSessionStatus,
21IAttachRequestArgs,
22ILaunchRequestArgs,
23} from "./debugSessionBase";
1bdccb66RedMickey6 years ago24import { JsDebugConfigAdapter } from "./jsDebugConfigAdapter";
d93677adRedMickey4 years ago25import { RNSession } from "./debugSessionWrapper";
09f6024fHeniker4 years ago26
34472878RedMickey5 years ago27nls.config({
28messageFormat: nls.MessageFormat.bundle,
29bundleFormat: nls.BundleFormat.standalone,
30})();
6e1bcd36RedMickey6 years ago31const localize = nls.loadMessageBundle();
32
2c19da7fRedMickey6 years ago33export class RNDebugSession extends DebugSessionBase {
e23d1841RedMickey6 years ago34private appWorker: MultipleLifetimesAppWorker | null;
6e491635RedMickey6 years ago35private onDidStartDebugSessionHandler: vscode.Disposable;
36private onDidTerminateDebugSessionHandler: vscode.Disposable;
6e1bcd36RedMickey6 years ago37
d93677adRedMickey4 years ago38constructor(rnSession: RNSession) {
39super(rnSession);
4c757eebRedMickey6 years ago40
41// variables definition
e23d1841RedMickey6 years ago42this.appWorker = null;
43
6e491635RedMickey6 years ago44this.onDidStartDebugSessionHandler = vscode.debug.onDidStartDebugSession(
34472878RedMickey5 years ago45this.handleStartDebugSession.bind(this),
4c757eebRedMickey6 years ago46);
47
6e491635RedMickey6 years ago48this.onDidTerminateDebugSessionHandler = vscode.debug.onDidTerminateDebugSession(
34472878RedMickey5 years ago49this.handleTerminateDebugSession.bind(this),
4c757eebRedMickey6 years ago50);
6e1bcd36RedMickey6 years ago51}
52
34472878RedMickey5 years ago53protected async launchRequest(
54response: DebugProtocol.LaunchResponse,
55launchArgs: ILaunchRequestArgs,
56// eslint-disable-next-line @typescript-eslint/no-unused-vars
57request?: DebugProtocol.Request,
58): Promise<void> {
0d77292aJiglioNero4 years ago59try {
60try {
4ccd0d65Ezio Li2 years ago61if (launchArgs.platform != "exponent") {
62await ReactNativeProjectHelper.verifyMetroConfigFile(launchArgs.cwd);
63}
0d77292aJiglioNero4 years ago64await this.initializeSettings(launchArgs);
65logger.log("Launching the application");
66logger.verbose(`Launching the application: ${JSON.stringify(launchArgs, null, 2)}`);
34472878RedMickey5 years ago67
0d77292aJiglioNero4 years ago68await this.appLauncher.launch(launchArgs);
69
70if (!launchArgs.enableDebug) {
71this.sendResponse(response);
72// if debugging is not enabled skip attach request
73return;
74}
75} catch (error) {
76throw ErrorHelper.getInternalError(
77InternalErrorCode.ApplicationLaunchFailed,
78error.message || error,
79);
80}
81// if debugging is enabled start attach request
d93677adRedMickey4 years ago82await this.vsCodeDebugSession.customRequest("attach", launchArgs);
83this.sendResponse(response);
0d77292aJiglioNero4 years ago84} catch (error) {
19df32dcRedMickey4 years ago85this.terminateWithErrorResponse(error, response);
0d77292aJiglioNero4 years ago86}
6e1bcd36RedMickey6 years ago87}
88
34472878RedMickey5 years ago89protected async attachRequest(
90response: DebugProtocol.AttachResponse,
91attachArgs: IAttachRequestArgs,
92// eslint-disable-next-line @typescript-eslint/no-unused-vars
93request?: DebugProtocol.Request,
94): Promise<void> {
6e1bcd36RedMickey6 years ago95let extProps = {
96platform: {
97value: attachArgs.platform,
98isPii: false,
99},
100};
101
102this.previousAttachArgs = attachArgs;
0d77292aJiglioNero4 years ago103
104return new Promise<void>(async (resolve, reject) => {
105try {
529a5336Ezio Li2 years ago106if (attachArgs.request === "attach") {
4ccd0d65Ezio Li2 years ago107const expoHelper = new ExponentHelper(attachArgs.cwd, attachArgs.cwd);
108const isExpo = await expoHelper.isExpoManagedApp(true);
109if (!isExpo) {
110await ReactNativeProjectHelper.verifyMetroConfigFile(attachArgs.cwd);
111}
529a5336Ezio Li2 years ago112}
0d77292aJiglioNero4 years ago113await this.initializeSettings(attachArgs);
114logger.log("Attaching to the application");
115logger.verbose(
116`Attaching to the application: ${JSON.stringify(attachArgs, null, 2)}`,
117);
118
119const versions = await ProjectVersionHelper.getReactNativeVersions(
120this.projectRootPath,
121ProjectVersionHelper.generateAdditionalPackagesToCheckByPlatform(attachArgs),
122);
123extProps = TelemetryHelper.addPlatformPropertiesToTelemetryProperties(
124attachArgs,
125versions,
126extProps,
127);
128
129// eslint-disable-next-line @typescript-eslint/no-unused-vars
130await TelemetryHelper.generate("attach", extProps, async generator => {
131attachArgs.port =
132attachArgs.port || this.appLauncher.getPackagerPort(attachArgs.cwd);
133
134const cdpProxy = this.appLauncher.getRnCdpProxy();
135await cdpProxy.stopServer();
136await cdpProxy.initializeServer(
137new RnCDPMessageHandler(),
138this.cdpProxyLogLevel,
dcabd9c8RedMickey4 years ago139this.cancellationTokenSource.token,
34472878RedMickey5 years ago140);
0d77292aJiglioNero4 years ago141
bfcc8a29Samriel4 years ago142if (attachArgs.request === "attach") {
143await this.preparePackagerBeforeAttach(attachArgs, versions);
144}
0d77292aJiglioNero4 years ago145
146logger.log(
147localize("StartingDebuggerAppWorker", "Starting debugger app worker."),
34472878RedMickey5 years ago148);
0d77292aJiglioNero4 years ago149
150const sourcesStoragePath = path.join(this.projectRootPath, ".vscode", ".react");
151// Create folder if not exist to avoid problems if
152// RN project root is not a ${workspaceFolder}
153mkdirp.sync(sourcesStoragePath);
154
155// If launch is invoked first time, appWorker is undefined, so create it here
156this.appWorker = new MultipleLifetimesAppWorker(
34472878RedMickey5 years ago157attachArgs,
0d77292aJiglioNero4 years ago158sourcesStoragePath,
159this.projectRootPath,
160this.cancellationTokenSource.token,
161undefined,
34472878RedMickey5 years ago162);
0d77292aJiglioNero4 years ago163this.appLauncher.setAppWorker(this.appWorker);
164
165this.appWorker.on("connected", (port: number) => {
166if (this.cancellationTokenSource.token.isCancellationRequested) {
167return this.appWorker?.stop();
168}
169
170logger.log(
171localize(
172"DebuggerWorkerLoadedRuntimeOnPort",
173"Debugger worker loaded runtime on port {0}",
174port,
175),
176);
177
178cdpProxy.setApplicationTargetPort(port);
179
180if (this.debugSessionStatus === DebugSessionStatus.ConnectionPending) {
181return;
182}
34472878RedMickey5 years ago183
0d77292aJiglioNero4 years ago184if (this.debugSessionStatus === DebugSessionStatus.FirstConnection) {
185this.debugSessionStatus = DebugSessionStatus.FirstConnectionPending;
186this.establishDebugSession(attachArgs, resolve);
187} else if (
188this.debugSessionStatus === DebugSessionStatus.ConnectionAllowed
189) {
190if (this.nodeSession) {
191this.debugSessionStatus = DebugSessionStatus.ConnectionPending;
09f6024fHeniker4 years ago192void this.nodeSession.customRequest(this.terminateCommand);
0d77292aJiglioNero4 years ago193}
194}
34472878RedMickey5 years ago195});
0d77292aJiglioNero4 years ago196
197if (this.cancellationTokenSource.token.isCancellationRequested) {
198return this.appWorker.stop();
199}
200return await this.appWorker.start();
201});
202} catch (error) {
203reject(error);
204}
d93677adRedMickey4 years ago205})
206.then(() => {
207this.sendResponse(response);
208})
209.catch(err =>
19df32dcRedMickey4 years ago210this.terminateWithErrorResponse(
d93677adRedMickey4 years ago211ErrorHelper.getInternalError(
212InternalErrorCode.CouldNotAttachToDebugger,
213err.message || err,
214),
215response,
0d77292aJiglioNero4 years ago216),
d93677adRedMickey4 years ago217);
6e1bcd36RedMickey6 years ago218}
219
34472878RedMickey5 years ago220protected async disconnectRequest(
221response: DebugProtocol.DisconnectResponse,
222args: DebugProtocol.DisconnectArguments,
223request?: DebugProtocol.Request,
224): Promise<void> {
6e1bcd36RedMickey6 years ago225// The client is about to disconnect so first we need to stop app worker
226if (this.appWorker) {
227this.appWorker.stop();
228}
229
6e491635RedMickey6 years ago230this.onDidStartDebugSessionHandler.dispose();
231this.onDidTerminateDebugSessionHandler.dispose();
232
0d77292aJiglioNero4 years ago233return super.disconnectRequest(response, args, request);
4c757eebRedMickey6 years ago234}
235
34472878RedMickey5 years ago236protected establishDebugSession(
237attachArgs: IAttachRequestArgs,
238resolve?: (value?: void | PromiseLike<void> | undefined) => void,
239): void {
1bdccb66RedMickey6 years ago240const attachConfiguration = JsDebugConfigAdapter.createDebuggingConfigForPureRN(
241attachArgs,
242this.appLauncher.getCdpProxyPort(),
d93677adRedMickey4 years ago243this.rnSession.sessionId,
1bdccb66RedMickey6 years ago244);
a6562589RedMickey6 years ago245
34472878RedMickey5 years ago246vscode.debug
247.startDebugging(this.appLauncher.getWorkspaceFolder(), attachConfiguration, {
d93677adRedMickey4 years ago248parentSession: this.vsCodeDebugSession,
ebbd64f1RedMickey6 years ago249consoleMode: vscode.DebugConsoleMode.MergeWithParent,
34472878RedMickey5 years ago250})
251.then(
252(childDebugSessionStarted: boolean) => {
253if (childDebugSessionStarted) {
254this.debugSessionStatus = DebugSessionStatus.ConnectionDone;
255this.setConnectionAllowedIfPossible();
256if (resolve) {
257this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
258resolve();
259}
260} else {
261this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
262this.setConnectionAllowedIfPossible();
263this.resetFirstConnectionStatus();
264throw new Error("Cannot start child debug session");
265}
266},
267err => {
268this.debugSessionStatus = DebugSessionStatus.ConnectionFailed;
269this.setConnectionAllowedIfPossible();
270this.resetFirstConnectionStatus();
271throw err;
272},
273);
4c757eebRedMickey6 years ago274}
6e1bcd36RedMickey6 years ago275
0d77292aJiglioNero4 years ago276private handleStartDebugSession(debugSession: vscode.DebugSession): void {
4c757eebRedMickey6 years ago277if (
d93677adRedMickey4 years ago278debugSession.configuration.rnDebugSessionId === this.rnSession.sessionId &&
34472878RedMickey5 years ago279debugSession.type === this.pwaNodeSessionName
4c757eebRedMickey6 years ago280) {
281this.nodeSession = debugSession;
282}
283}
284
0d77292aJiglioNero4 years ago285private handleTerminateDebugSession(debugSession: vscode.DebugSession): void {
4c757eebRedMickey6 years ago286if (
d93677adRedMickey4 years ago287debugSession.configuration.rnDebugSessionId === this.rnSession.sessionId &&
34472878RedMickey5 years ago288debugSession.type === this.pwaNodeSessionName
4c757eebRedMickey6 years ago289) {
ebbd64f1RedMickey6 years ago290if (this.debugSessionStatus === DebugSessionStatus.ConnectionPending) {
5d47053fRedMickey6 years ago291this.establishDebugSession(this.previousAttachArgs);
ebbd64f1RedMickey6 years ago292} else {
19df32dcRedMickey4 years ago293void this.terminate();
ebbd64f1RedMickey6 years ago294}
4c757eebRedMickey6 years ago295}
296}
297
298private setConnectionAllowedIfPossible(): void {
299if (
34472878RedMickey5 years ago300this.debugSessionStatus === DebugSessionStatus.ConnectionDone ||
301this.debugSessionStatus === DebugSessionStatus.ConnectionFailed
4c757eebRedMickey6 years ago302) {
303this.debugSessionStatus = DebugSessionStatus.ConnectionAllowed;
304}
305}
306
307private resetFirstConnectionStatus(): void {
308if (this.debugSessionStatus === DebugSessionStatus.FirstConnectionPending) {
309this.debugSessionStatus = DebugSessionStatus.FirstConnection;
310}
311}
6e1bcd36RedMickey6 years ago312}