microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9e81e40f4152f5c42f065e1b0f4a4995b93b96af

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/nodeDebugWrapper.ts

194lines · modeblame

65bb0c85Jimmy Thomson10 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
d976d077Meena Kunnathur Balakrishnan10 years ago4import * as fs from "fs";
65bb0c85Jimmy Thomson10 years ago5import * as path from "path";
6import * as http from "http";
7
d976d077Meena Kunnathur Balakrishnan10 years ago8import {Telemetry} from "../common/telemetry";
dd442738Jimmy Thomson10 years ago9import {TelemetryHelper} from "../common/telemetryHelper";
725cf712digeff10 years ago10import {RemoteExtension} from "../common/remoteExtension";
18d8ad2adigeff10 years ago11import {EntryPointHandler, ProcessType} from "../common/entryPointHandler";
12import {ErrorHelper} from "../common/error/errorHelper";
13import {InternalErrorCode} from "../common/error/internalErrorCode";
bb77358cMark Oswald10 years ago14import {IOSPlatform} from "./ios/iOSPlatform";
18d8ad2adigeff10 years ago15import {ExtensionTelemetryReporter, NullTelemetryReporter, ReassignableTelemetryReporter} from "../common/telemetryReporters";
d976d077Meena Kunnathur Balakrishnan10 years ago16
65bb0c85Jimmy Thomson10 years ago17// These typings do not reflect the typings as intended to be used
18// but rather as they exist in truth, so we can reach into the internals
19// and access what we need.
20declare module VSCodeDebugAdapter {
21class DebugSession {
22public static run: Function;
5547a16fJimmy Thomson10 years ago23public sendEvent(event: VSCodeDebugAdapter.InitializedEvent): void;
24public start(input: any, output: any): void;
25public launchRequest(response: any, args: any): void;
c2bf3c4fdigeff10 years ago26public disconnectRequest(response: any, args: any): void;
65bb0c85Jimmy Thomson10 years ago27}
28class InitializedEvent {
5547a16fJimmy Thomson10 years ago29constructor();
30}
31class OutputEvent {
32constructor(message: string, destination?: string);
33}
34class TerminatedEvent {
35constructor();
65bb0c85Jimmy Thomson10 years ago36}
37}
38
39declare class SourceMaps {
40public _sourceToGeneratedMaps: {};
41public _generatedToSourceMaps: {};
42public _allSourceMaps: {};
43}
44
5547a16fJimmy Thomson10 years ago45declare class NodeDebugSession extends VSCodeDebugAdapter.DebugSession {
65bb0c85Jimmy Thomson10 years ago46public _sourceMaps: SourceMaps;
47}
48
5e54f6f2Jimmy Thomson10 years ago49interface ILaunchArgs {
50platform: string;
51target?: string;
52internalDebuggerPort?: any;
bb77358cMark Oswald10 years ago53iosRelativeProjectPath?: string;
5e54f6f2Jimmy Thomson10 years ago54args: string[];
710f8655digeff10 years ago55logCatArguments: any;
4f4e082ddigeff10 years ago56program: string;
5e54f6f2Jimmy Thomson10 years ago57}
58
2d3a052eMeena Kunnathur Balakrishnan10 years ago59let version = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf-8")).version;
5547a16fJimmy Thomson10 years ago60
642490c1Jimmy Thomson10 years ago61function bailOut(reason: string): void {
62// Things have gone wrong in initialization: Report the error to telemetry and exit
63TelemetryHelper.sendSimpleEvent(reason);
6e4d7a62Joshua Skelton10 years ago64process.exit(1);
642490c1Jimmy Thomson10 years ago65}
66
c31e59fbdigeff10 years ago67function parseLogCatArguments(userProvidedLogCatArguments: any) {
68return Array.isArray(userProvidedLogCatArguments)
69? userProvidedLogCatArguments.join(" ") // If it's an array, we join the arguments
70: userProvidedLogCatArguments; // If not, we leave it as-is
71}
72
73function isNullOrUndefined(value: any): boolean {
74return typeof value === "undefined" || value === null;
75}
76
4f4e082ddigeff10 years ago77let projectRootPath: string = null;
78
2d3a052eMeena Kunnathur Balakrishnan10 years ago79// Enable telemetry
18d8ad2adigeff10 years ago80const telemetryReporter = new ReassignableTelemetryReporter(new NullTelemetryReporter());
81const appName = "react-native-debug-adapter";
82new EntryPointHandler(ProcessType.Debugger).runApp(appName, () => version,
83ErrorHelper.getInternalError(InternalErrorCode.DebuggingFailed), telemetryReporter, () => {
84let nodeDebugFolder: string;
85let vscodeDebugAdapterPackage: typeof VSCodeDebugAdapter;
86
87// nodeDebugLocation.json is dynamically generated on extension activation.
88// If it fails, we must not have been in a react native project
89try {
90/* tslint:disable:no-var-requires */
91nodeDebugFolder = require("./nodeDebugLocation.json").nodeDebugPath;
92vscodeDebugAdapterPackage = require(path.join(nodeDebugFolder, "node_modules", "vscode-debugadapter"));
93/* tslint:enable:no-var-requires */
94} catch (e) {
95// Nothing we can do here: can't even communicate back because we don't know how to speak debug adapter
96bailOut("cannotFindDebugAdapter");
97}
4881129dMeena Kunnathur Balakrishnan10 years ago98
18d8ad2adigeff10 years ago99// Temporarily dummy out the DebugSession.run function so we do not start the debug adapter until we are ready
100const originalDebugSessionRun = vscodeDebugAdapterPackage.DebugSession.run;
101vscodeDebugAdapterPackage.DebugSession.run = function() { };
4881129dMeena Kunnathur Balakrishnan10 years ago102
18d8ad2adigeff10 years ago103let nodeDebug: { NodeDebugSession: typeof NodeDebugSession };
dd442738Jimmy Thomson10 years ago104
18d8ad2adigeff10 years ago105try {
106/* tslint:disable:no-var-requires */
107nodeDebug = require(path.join(nodeDebugFolder, "out", "node", "nodeDebug"));
108/* tslint:enable:no-var-requires */
109} catch (e) {
110// Unable to find nodeDebug, but we can make our own communication channel now
111const debugSession = new vscodeDebugAdapterPackage.DebugSession();
112// Note: this will not work in the context of debugging the debug adapter and communicating over a socket,
113// but in that case we have much better ways to investigate errors.
114debugSession.start(process.stdin, process.stdout);
115debugSession.sendEvent(new vscodeDebugAdapterPackage.OutputEvent("Unable to start debug adapter: " + e.toString(), "stderr"));
116debugSession.sendEvent(new vscodeDebugAdapterPackage.TerminatedEvent());
117
118bailOut("cannotFindNodeDebugAdapter");
119}
2d3a052eMeena Kunnathur Balakrishnan10 years ago120
18d8ad2adigeff10 years ago121vscodeDebugAdapterPackage.DebugSession.run = originalDebugSessionRun;
122
123// Intecept the "launchRequest" instance method of NodeDebugSession to interpret arguments
124const originalNodeDebugSessionLaunchRequest = nodeDebug.NodeDebugSession.prototype.launchRequest;
125nodeDebug.NodeDebugSession.prototype.launchRequest = function(request: any, args: ILaunchArgs) {
126projectRootPath = path.resolve(args.program, "../..");
127telemetryReporter.reassignTo(new ExtensionTelemetryReporter( // We start to send telemetry
128appName, version, Telemetry.APPINSIGHTS_INSTRUMENTATIONKEY, projectRootPath));
129
130// Create a server waiting for messages to re-initialize the debug session;
131const reinitializeServer = http.createServer((req, res) => {
132res.statusCode = 404;
133if (req.url === "/refreshBreakpoints") {
134res.statusCode = 200;
135if (this) {
136const sourceMaps = this._sourceMaps;
137if (sourceMaps) {
138// Flush any cached source maps
139sourceMaps._allSourceMaps = {};
140sourceMaps._generatedToSourceMaps = {};
141sourceMaps._sourceToGeneratedMaps = {};
142}
143// Send an "initialized" event to trigger breakpoints to be re-sent
144this.sendEvent(new vscodeDebugAdapterPackage.InitializedEvent());
48efc4d6Meena Kunnathur Balakrishnan10 years ago145}
4881129dMeena Kunnathur Balakrishnan10 years ago146}
18d8ad2adigeff10 years ago147res.end();
148});
149const debugServerListeningPort = parseInt(args.internalDebuggerPort, 10) || 9090;
150
151
152reinitializeServer.listen(debugServerListeningPort);
153reinitializeServer.on("error", (err: Error) => {
154TelemetryHelper.sendSimpleEvent("reinitializeServerError");
155this.sendEvent(new vscodeDebugAdapterPackage.OutputEvent("Error in debug adapter server: " + err.toString(), "stderr"));
156this.sendEvent(new vscodeDebugAdapterPackage.OutputEvent("Breakpoints may not update. Consider restarting and specifying a different 'internalDebuggerPort' in launch.json"));
157});
158
159// We do not permit arbitrary args to be passed to our process
160args.args = [
161args.platform,
162debugServerListeningPort.toString(),
d235274fMark Oswald10 years ago163!isNullOrUndefined(args.iosRelativeProjectPath) ? args.iosRelativeProjectPath : IOSPlatform.DEFAULT_IOS_PROJECT_RELATIVE_PATH,
18d8ad2adigeff10 years ago164args.target || "simulator",
165];
c96fc63eMark Oswald10 years ago166
18d8ad2adigeff10 years ago167if (!isNullOrUndefined(args.logCatArguments)) { // We add the parameter if it's defined (adapter crashes otherwise)
168args.args = args.args.concat([parseLogCatArguments(args.logCatArguments)]);
4881129dMeena Kunnathur Balakrishnan10 years ago169}
710f8655digeff10 years ago170
18d8ad2adigeff10 years ago171originalNodeDebugSessionLaunchRequest.call(this, request, args);
172};
173
174// Intecept the "launchRequest" instance method of NodeDebugSession to interpret arguments
175const originalNodeDebugSessionDisconnectRequest = nodeDebug.NodeDebugSession.prototype.disconnectRequest;
176function customDisconnectRequest(response: any, args: any): void {
177try {
178// First we tell the extension to stop monitoring the logcat, and then we disconnect the debugging session
c7f1165cdigeff10 years ago179const remoteExtension = RemoteExtension.atProjectRootPath(projectRootPath);
0766856fdigeff10 years ago180remoteExtension.stopMonitoringLogcat()
18d8ad2adigeff10 years ago181.finally(() => originalNodeDebugSessionDisconnectRequest.call(this, response, args))
182.done(() => { }, reason => // We just print a warning if something fails
183process.stderr.write(`WARNING: Couldn't stop monitoring logcat: ${reason.message || reason}\n`));
184} catch (exception) {
185// This is a "nice to have" feature, so we just fire the message and forget. We don't event handle
186// errors in the response promise
187process.stderr.write(`WARNING: Couldn't stop monitoring logcat. Sync exception: ${exception.message || exception}\n`);
188originalNodeDebugSessionDisconnectRequest.call(this, response, args);
4881129dMeena Kunnathur Balakrishnan10 years ago189}
c2bf3c4fdigeff10 years ago190}
18d8ad2adigeff10 years ago191nodeDebug.NodeDebugSession.prototype.disconnectRequest = customDisconnectRequest;
c2bf3c4fdigeff10 years ago192
18d8ad2adigeff10 years ago193vscodeDebugAdapterPackage.DebugSession.run(nodeDebug.NodeDebugSession);
41c61f9aJoshua Skelton10 years ago194});