microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
6e491635e08c261310d93f18da08074c210b3da2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/cdp-proxy/reactNativeCDPProxy.ts

139lines · modeblame

f872f4d5RedMickey6 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 {
5Connection,
6Server,
7WebSocketTransport,
8IProtocolCommand,
9IProtocolError,
10IProtocolSuccess
11} from "vscode-cdp-proxy";
af1b9666RedMickey6 years ago12import { IncomingMessage } from "http";
f872f4d5RedMickey6 years ago13import { OutputChannelLogger } from "../extension/log/OutputChannelLogger";
a324603aRedMickey6 years ago14import { LogLevel } from "../extension/log/LogHelper";
d9c9ddcbRedMickey6 years ago15import { DebuggerEndpointHelper } from "./debuggerEndpointHelper";
f872f4d5RedMickey6 years ago16
17export class ReactNativeCDPProxy {
18
a324603aRedMickey6 years ago19private readonly PROXY_LOG_TAGS = {
20DEBUGGER_COMMAND: "Command Debugger To Target",
21APPLICATION_COMMAND: "Command Target To Debugger",
22DEBUGGER_REPLY: "Reply From Debugger To Target",
23APPLICATION_REPLY: "Reply From Target To Debugger",
24};
25
d9c9ddcbRedMickey6 years ago26private server: Server | null;
27private hostAddress: string;
28private port: number;
29private debuggerTarget: Connection;
30private applicationTarget: Connection;
31private logger: OutputChannelLogger;
32private logLevel: LogLevel;
33private firstStop: boolean;
34private debuggerEndpointHelper: DebuggerEndpointHelper;
35private applicationTargetPort: number;
36
a324603aRedMickey6 years ago37constructor(hostAddress: string, port: number, logLevel: LogLevel) {
f872f4d5RedMickey6 years ago38this.port = port;
39this.hostAddress = hostAddress;
a324603aRedMickey6 years ago40this.logger = OutputChannelLogger.getChannel("React Native Chrome Proxy", true, false, true);
f872f4d5RedMickey6 years ago41this.logLevel = logLevel;
d9c9ddcbRedMickey6 years ago42this.firstStop = true;
43this.debuggerEndpointHelper = new DebuggerEndpointHelper();
f872f4d5RedMickey6 years ago44}
45
46public createServer(): Promise<void> {
47return Server.create({ port: this.port, host: this.hostAddress })
48.then((server: Server) => {
49this.server = server;
50this.server.onConnection(this.onConnectionHandler.bind(this));
51});
52}
53
54public stopServer(): void {
55if (this.server) {
56this.server.dispose();
57this.server = null;
58}
59}
60
d9c9ddcbRedMickey6 years ago61public setApplicationTargetPort(applicationTargetPort: number): void {
62this.applicationTargetPort = applicationTargetPort;
f872f4d5RedMickey6 years ago63}
64
65private async onConnectionHandler([debuggerTarget, request]: [Connection, IncomingMessage]): Promise<void> {
66this.debuggerTarget = debuggerTarget;
67
68this.debuggerTarget.pause(); // don't listen for events until the target is ready
69
d9c9ddcbRedMickey6 years ago70const browserInspectUri = await this.debuggerEndpointHelper.getWSEndpoint(`http://localhost:${this.applicationTargetPort}`);
71
f872f4d5RedMickey6 years ago72this.applicationTarget = new Connection(await WebSocketTransport.create(browserInspectUri));
73
74this.applicationTarget.onError(this.onApplicationTargetError.bind(this));
75this.debuggerTarget.onError(this.onDebuggerTargetError.bind(this));
76
77this.applicationTarget.onCommand(this.handleApplicationTargetCommand.bind(this));
78this.debuggerTarget.onCommand(this.handleDebuggerTargetCommand.bind(this));
79
80this.applicationTarget.onReply(this.handleApplicationTargetReply.bind(this));
81this.debuggerTarget.onReply(this.handleDebuggerTargetReply.bind(this));
82
4c757eebRedMickey6 years ago83this.debuggerTarget.onEnd(this.onDebuggerTargetClosed.bind(this));
af1b9666RedMickey6 years ago84
f872f4d5RedMickey6 years ago85// dequeue any messages we got in the meantime
86this.debuggerTarget.unpause();
87}
88
89private handleDebuggerTargetCommand(evt: IProtocolCommand) {
a324603aRedMickey6 years ago90this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_COMMAND, JSON.stringify(evt, null , 2), this.logLevel);
f872f4d5RedMickey6 years ago91this.applicationTarget.send(evt);
92}
93
94private handleApplicationTargetCommand(evt: IProtocolCommand) {
5aead7e7Yuri Skorokhodov6 years ago95if (evt.method === "Debugger.paused" && this.firstStop) {
96evt.params = this.handleAppBundleFirstPauseEvent(evt);
97}
a324603aRedMickey6 years ago98this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_COMMAND, JSON.stringify(evt, null , 2), this.logLevel);
f872f4d5RedMickey6 years ago99this.debuggerTarget.send(evt);
100}
101
5aead7e7Yuri Skorokhodov6 years ago102/** Since the bundle runs inside the Node.js VM in `debuggerWorker.js` in runtime
103* Node debug adapter need time to parse new added code source maps
104* So we added `debugger;` statement at the start of the bundle code
105* and wait for the adapter to receive a signal to stop on that statement
106* and then change pause reason to `Break on start` so js-debug can process all breakpoints in the bundle and
107* continue the code execution using `continueOnAttach` flag
a324603aRedMickey6 years ago108*/
5aead7e7Yuri Skorokhodov6 years ago109private handleAppBundleFirstPauseEvent(evt: IProtocolCommand): any {
110let params: any = evt.params;
111if (params.reason && params.reason === "other") {
112this.firstStop = false;
113params.reason = "Break on start";
114}
115return params;
116}
117
f872f4d5RedMickey6 years ago118private handleDebuggerTargetReply(evt: IProtocolError | IProtocolSuccess) {
a324603aRedMickey6 years ago119this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.DEBUGGER_REPLY, JSON.stringify(evt, null , 2), this.logLevel);
f872f4d5RedMickey6 years ago120this.applicationTarget.send(evt);
121}
122
123private handleApplicationTargetReply(evt: IProtocolError | IProtocolSuccess) {
a324603aRedMickey6 years ago124this.logger.logWithCustomTag(this.PROXY_LOG_TAGS.APPLICATION_REPLY, JSON.stringify(evt, null , 2), this.logLevel);
f872f4d5RedMickey6 years ago125this.debuggerTarget.send(evt);
126}
127
128private onDebuggerTargetError(err: Error) {
a324603aRedMickey6 years ago129this.logger.error("Error on debugger transport", err);
f872f4d5RedMickey6 years ago130}
131
132private onApplicationTargetError(err: Error) {
a324603aRedMickey6 years ago133this.logger.error("Error on application transport", err);
f872f4d5RedMickey6 years ago134}
135
4c757eebRedMickey6 years ago136private async onDebuggerTargetClosed() {
5aead7e7Yuri Skorokhodov6 years ago137this.firstStop = true;
af1b9666RedMickey6 years ago138}
f872f4d5RedMickey6 years ago139}