microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
960a6ec47eafad42cd52a36af455604d4650cfff

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/direct/directDebugSession.ts

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