microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1c2424f4d9af42a0cefcacb0fcb9670b5aa292cd

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/direct/directDebugSession.ts

302lines · modecode

1// 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 { ProjectVersionHelper } from "../../common/projectVersionHelper";
6import { logger } from "vscode-debugadapter";
7import { TelemetryHelper } from "../../common/telemetryHelper";
8import { DebugProtocol } from "vscode-debugprotocol";
9import { HermesCDPMessageHandler } from "../../cdp-proxy/CDPMessageHandlers/hermesCDPMessageHandler";
10import { DebugSessionBase, IAttachRequestArgs, ILaunchRequestArgs } from "../debugSessionBase";
11import { JsDebugConfigAdapter } from "../jsDebugConfigAdapter";
12import { DebuggerEndpointHelper } from "../../cdp-proxy/debuggerEndpointHelper";
13import { ErrorHelper } from "../../common/error/errorHelper";
14import { InternalErrorCode } from "../../common/error/internalErrorCode";
15import * as nls from "vscode-nls";
16import { IOSDirectCDPMessageHandler } from "../../cdp-proxy/CDPMessageHandlers/iOSDirectCDPMessageHandler";
17import { PlatformType } from "../../extension/launchArgs";
18import { IWDPHelper } from "./IWDPHelper";
19import { BaseCDPMessageHandler } from "../../cdp-proxy/CDPMessageHandlers/baseCDPMessageHandler";
20
21nls.config({
22 messageFormat: nls.MessageFormat.bundle,
23 bundleFormat: nls.BundleFormat.standalone,
24})();
25const localize = nls.loadMessageBundle();
26
27export class DirectDebugSession extends DebugSessionBase {
28 private debuggerEndpointHelper: DebuggerEndpointHelper;
29 private onDidTerminateDebugSessionHandler: vscode.Disposable;
30 private iOSWKDebugProxyHelper: IWDPHelper;
31
32 constructor(session: vscode.DebugSession) {
33 super(session);
34 this.debuggerEndpointHelper = new DebuggerEndpointHelper();
35 this.iOSWKDebugProxyHelper = new IWDPHelper();
36
37 this.onDidTerminateDebugSessionHandler = vscode.debug.onDidTerminateDebugSession(
38 this.handleTerminateDebugSession.bind(this),
39 );
40 }
41
42 protected async launchRequest(
43 response: DebugProtocol.LaunchResponse,
44 launchArgs: ILaunchRequestArgs,
45 // eslint-disable-next-line @typescript-eslint/no-unused-vars
46 request?: DebugProtocol.Request,
47 ): Promise<void> {
48 let extProps = {
49 platform: {
50 value: launchArgs.platform,
51 isPii: false,
52 },
53 isDirect: {
54 value: true,
55 isPii: false,
56 },
57 };
58
59 return new Promise<void>((resolve, reject) =>
60 this.initializeSettings(launchArgs)
61 .then(() => {
62 logger.log("Launching the application");
63 logger.verbose(
64 `Launching the application: ${JSON.stringify(launchArgs, null, 2)}`,
65 );
66
67 return ProjectVersionHelper.getReactNativeVersions(
68 this.projectRootPath,
69 ProjectVersionHelper.generateAdditionalPackagesToCheckByPlatform(
70 launchArgs,
71 ),
72 );
73 })
74 .then(versions => {
75 extProps = TelemetryHelper.addPlatformPropertiesToTelemetryProperties(
76 launchArgs,
77 versions,
78 extProps,
79 );
80
81 // eslint-disable-next-line @typescript-eslint/no-unused-vars
82 return TelemetryHelper.generate("launch", extProps, generator => {
83 return this.appLauncher.launch(launchArgs).then(() => {
84 if (launchArgs.enableDebug) {
85 this.attachRequest(response, launchArgs)
86 .then(() => {
87 resolve();
88 })
89 .catch(e => reject(e));
90 } else {
91 this.sendResponse(response);
92 resolve();
93 }
94 });
95 });
96 })
97 .catch(err => {
98 reject(
99 ErrorHelper.getInternalError(
100 InternalErrorCode.ApplicationLaunchFailed,
101 err.message || err,
102 ),
103 );
104 }),
105 ).catch(err => this.showError(err, response));
106 }
107
108 protected async attachRequest(
109 response: DebugProtocol.AttachResponse,
110 attachArgs: IAttachRequestArgs,
111 // eslint-disable-next-line @typescript-eslint/no-unused-vars
112 request?: DebugProtocol.Request,
113 ): Promise<void> {
114 let extProps = {
115 platform: {
116 value: attachArgs.platform,
117 isPii: false,
118 },
119 isDirect: {
120 value: true,
121 isPii: false,
122 },
123 };
124
125 attachArgs.webkitRangeMin = attachArgs.webkitRangeMin || 9223;
126 attachArgs.webkitRangeMax = attachArgs.webkitRangeMax || 9322;
127
128 this.previousAttachArgs = attachArgs;
129
130 return new Promise<void>((resolve, reject) =>
131 this.initializeSettings(attachArgs)
132 .then(() => {
133 logger.log("Attaching to the application");
134 logger.verbose(
135 `Attaching to the application: ${JSON.stringify(attachArgs, null, 2)}`,
136 );
137 return ProjectVersionHelper.getReactNativeVersions(
138 this.projectRootPath,
139 ProjectVersionHelper.generateAdditionalPackagesToCheckByPlatform(
140 attachArgs,
141 ),
142 );
143 })
144 .then(versions => {
145 extProps = TelemetryHelper.addPlatformPropertiesToTelemetryProperties(
146 attachArgs,
147 versions,
148 extProps,
149 );
150
151 // eslint-disable-next-line @typescript-eslint/no-unused-vars
152 return TelemetryHelper.generate("attach", extProps, generator => {
153 const port = attachArgs.useHermesEngine
154 ? attachArgs.port || this.appLauncher.getPackagerPort(attachArgs.cwd)
155 : attachArgs.platform === PlatformType.iOS
156 ? attachArgs.port || IWDPHelper.iOS_WEBKIT_DEBUG_PROXY_DEFAULT_PORT
157 : null;
158 if (port === null) {
159 return Promise.reject(
160 ErrorHelper.getInternalError(
161 InternalErrorCode.CouldNotDirectDebugWithoutHermesEngine,
162 attachArgs.platform,
163 ),
164 );
165 }
166 attachArgs.port = port;
167 logger.log(`Connecting to ${attachArgs.port} port`);
168 return this.appLauncher
169 .getRnCdpProxy()
170 .stopServer()
171 .then(() => {
172 const cdpProxy: BaseCDPMessageHandler | null = attachArgs.useHermesEngine
173 ? new HermesCDPMessageHandler()
174 : attachArgs.platform === PlatformType.iOS
175 ? new IOSDirectCDPMessageHandler()
176 : null;
177
178 if (!cdpProxy) {
179 return Promise.reject(
180 ErrorHelper.getInternalError(
181 InternalErrorCode.CouldNotDirectDebugWithoutHermesEngine,
182 attachArgs.platform,
183 ),
184 );
185 }
186 return this.appLauncher
187 .getRnCdpProxy()
188 .initializeServer(cdpProxy, this.cdpProxyLogLevel);
189 })
190 .then(() => {
191 if (
192 !attachArgs.useHermesEngine &&
193 attachArgs.platform === PlatformType.iOS
194 ) {
195 return this.iOSWKDebugProxyHelper
196 .startiOSWebkitDebugProxy(
197 attachArgs.port,
198 attachArgs.webkitRangeMin,
199 attachArgs.webkitRangeMax,
200 )
201 .then(() =>
202 this.iOSWKDebugProxyHelper.getSimulatorProxyPort(
203 attachArgs,
204 ),
205 )
206 .then(results => {
207 attachArgs.port = results.targetPort;
208 });
209 } else {
210 return Promise.resolve();
211 }
212 })
213 .then(() => this.appLauncher.getPackager().start())
214 .then(() =>
215 this.debuggerEndpointHelper.retryGetWSEndpoint(
216 `http://localhost:${attachArgs.port}`,
217 90,
218 this.cancellationTokenSource.token,
219 ),
220 )
221 .then(browserInspectUri => {
222 this.appLauncher
223 .getRnCdpProxy()
224 .setBrowserInspectUri(browserInspectUri);
225 this.establishDebugSession(attachArgs, resolve);
226 })
227 .catch(e => reject(e));
228 });
229 })
230 .catch(err => {
231 reject(
232 ErrorHelper.getInternalError(
233 InternalErrorCode.CouldNotAttachToDebugger,
234 err.message || err,
235 ),
236 );
237 }),
238 ).catch(err => this.showError(err, response));
239 }
240
241 protected async disconnectRequest(
242 response: DebugProtocol.DisconnectResponse,
243 args: DebugProtocol.DisconnectArguments,
244 request?: DebugProtocol.Request,
245 ): Promise<void> {
246 this.iOSWKDebugProxyHelper.cleanUp();
247 this.onDidTerminateDebugSessionHandler.dispose();
248 super.disconnectRequest(response, args, request);
249 }
250
251 protected establishDebugSession(
252 attachArgs: IAttachRequestArgs,
253 resolve?: (value?: void | PromiseLike<void> | undefined) => void,
254 ): void {
255 const attachConfiguration = JsDebugConfigAdapter.createDebuggingConfigForRNHermes(
256 attachArgs,
257 this.appLauncher.getCdpProxyPort(),
258 this.session.id,
259 );
260
261 vscode.debug
262 .startDebugging(this.appLauncher.getWorkspaceFolder(), attachConfiguration, {
263 parentSession: this.session,
264 consoleMode: vscode.DebugConsoleMode.MergeWithParent,
265 })
266 .then(
267 (childDebugSessionStarted: boolean) => {
268 if (childDebugSessionStarted) {
269 if (resolve) {
270 resolve();
271 }
272 } else {
273 throw new Error(
274 localize(
275 "CouldNotStartChildDebugSession",
276 "Couldn't start child debug session",
277 ),
278 );
279 }
280 },
281 err => {
282 throw err;
283 },
284 );
285 }
286
287 private handleTerminateDebugSession(debugSession: vscode.DebugSession) {
288 if (
289 debugSession.configuration.rnDebugSessionId === this.session.id &&
290 debugSession.type === this.pwaNodeSessionName
291 ) {
292 vscode.commands.executeCommand(this.stopCommand, this.session);
293 }
294 }
295
296 protected async initializeSettings(args: any): Promise<any> {
297 await super.initializeSettings(args);
298 if (args.useHermesEngine === undefined) {
299 args.useHermesEngine = true;
300 }
301 }
302}
303