@react-native/dev-middleware 0.75.0-rc.2 → 0.76.0-nightly-20240628-TEMP
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createDevMiddleware.js +0 -11
- package/dist/inspector-proxy/Device.d.ts +10 -1
- package/dist/inspector-proxy/Device.js +119 -256
- package/dist/inspector-proxy/Device.js.flow +10 -1
- package/dist/inspector-proxy/DeviceEventReporter.d.ts +2 -1
- package/dist/inspector-proxy/DeviceEventReporter.js +0 -11
- package/dist/inspector-proxy/DeviceEventReporter.js.flow +2 -1
- package/dist/inspector-proxy/InspectorProxy.d.ts +4 -0
- package/dist/inspector-proxy/InspectorProxy.js +24 -91
- package/dist/inspector-proxy/InspectorProxy.js.flow +4 -0
- package/dist/inspector-proxy/cdp-types/messages.d.ts +10 -9
- package/dist/inspector-proxy/cdp-types/messages.js.flow +12 -11
- package/dist/inspector-proxy/cdp-types/protocol.d.ts +14 -10
- package/dist/inspector-proxy/cdp-types/protocol.js.flow +13 -11
- package/dist/inspector-proxy/types.d.ts +6 -0
- package/dist/inspector-proxy/types.js.flow +7 -0
- package/dist/middleware/deprecated_openFlipperMiddleware.js +0 -18
- package/dist/middleware/openDebuggerMiddleware.js +25 -38
- package/dist/utils/DefaultBrowserLauncher.js +0 -24
- package/dist/utils/getDevToolsFrontendUrl.js +0 -17
- package/package.json +3 -3
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type { EventReporter } from "../types/EventReporter";
|
|
12
12
|
import type { CDPResponse } from "./cdp-types/messages";
|
|
13
|
+
import type { DeepReadOnly } from "./types";
|
|
13
14
|
type DeviceMetadata = Readonly<{
|
|
14
15
|
appId: string;
|
|
15
16
|
deviceId: string;
|
|
@@ -33,7 +34,7 @@ declare class DeviceEventReporter {
|
|
|
33
34
|
metadata: RequestMetadata
|
|
34
35
|
): void;
|
|
35
36
|
logResponse(
|
|
36
|
-
res: CDPResponse
|
|
37
|
+
res: DeepReadOnly<CDPResponse<>>,
|
|
37
38
|
origin: "device" | "proxy",
|
|
38
39
|
metadata: ResponseMetadata
|
|
39
40
|
): void;
|
|
@@ -8,23 +8,12 @@ var _ttlcache = _interopRequireDefault(require("@isaacs/ttlcache"));
|
|
|
8
8
|
function _interopRequireDefault(obj) {
|
|
9
9
|
return obj && obj.__esModule ? obj : { default: obj };
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
13
|
-
*
|
|
14
|
-
* This source code is licensed under the MIT license found in the
|
|
15
|
-
* LICENSE file in the root directory of this source tree.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @format
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
11
|
class DeviceEventReporter {
|
|
22
12
|
#eventReporter;
|
|
23
13
|
#pendingCommands = new _ttlcache.default({
|
|
24
14
|
ttl: 10000,
|
|
25
15
|
dispose: (command, id, reason) => {
|
|
26
16
|
if (reason === "delete" || reason === "set") {
|
|
27
|
-
// TODO: Report clobbering ('set') using a dedicated error code
|
|
28
17
|
return;
|
|
29
18
|
}
|
|
30
19
|
this.#logExpiredCommand(command);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type { EventReporter } from "../types/EventReporter";
|
|
12
12
|
import type { CDPResponse } from "./cdp-types/messages";
|
|
13
|
+
import type { DeepReadOnly } from "./types";
|
|
13
14
|
|
|
14
15
|
type DeviceMetadata = $ReadOnly<{
|
|
15
16
|
appId: string,
|
|
@@ -37,7 +38,7 @@ declare class DeviceEventReporter {
|
|
|
37
38
|
metadata: RequestMetadata
|
|
38
39
|
): void;
|
|
39
40
|
logResponse(
|
|
40
|
-
res: CDPResponse
|
|
41
|
+
res: DeepReadOnly<CDPResponse<>>,
|
|
41
42
|
origin: "device" | "proxy",
|
|
42
43
|
metadata: ResponseMetadata
|
|
43
44
|
): void;
|
|
@@ -16,6 +16,10 @@ import type { PageDescription } from "./types";
|
|
|
16
16
|
import type { IncomingMessage, ServerResponse } from "http";
|
|
17
17
|
import WS from "ws";
|
|
18
18
|
export interface InspectorProxyQueries {
|
|
19
|
+
/**
|
|
20
|
+
* Returns list of page descriptions ordered by device connection order, then
|
|
21
|
+
* page addition order.
|
|
22
|
+
*/
|
|
19
23
|
getPageDescriptions(): Array<PageDescription>;
|
|
20
24
|
}
|
|
21
25
|
/**
|
|
@@ -12,22 +12,6 @@ var _ws = _interopRequireDefault(require("ws"));
|
|
|
12
12
|
function _interopRequireDefault(obj) {
|
|
13
13
|
return obj && obj.__esModule ? obj : { default: obj };
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
17
|
-
*
|
|
18
|
-
* This source code is licensed under the MIT license found in the
|
|
19
|
-
* LICENSE file in the root directory of this source tree.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* @format
|
|
23
|
-
* @oncall react_native
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
// $FlowFixMe[cannot-resolve-module] libdef missing in RN OSS
|
|
27
|
-
|
|
28
|
-
// Import these from node:timers to get the correct Flow types.
|
|
29
|
-
// $FlowFixMe[cannot-resolve-module] libdef missing in RN OSS
|
|
30
|
-
|
|
31
15
|
const debug = require("debug")("Metro:InspectorProxy");
|
|
32
16
|
const WS_DEVICE_URL = "/inspector/device";
|
|
33
17
|
const WS_DEBUGGER_URL = "/inspector/debug";
|
|
@@ -37,25 +21,13 @@ const PAGES_LIST_JSON_VERSION_URL = "/json/version";
|
|
|
37
21
|
const MAX_PONG_LATENCY_MS = 5000;
|
|
38
22
|
const DEBUGGER_HEARTBEAT_INTERVAL_MS = 10000;
|
|
39
23
|
const INTERNAL_ERROR_CODE = 1011;
|
|
40
|
-
/**
|
|
41
|
-
* Main Inspector Proxy class that connects JavaScript VM inside Android/iOS apps and JS debugger.
|
|
42
|
-
*/
|
|
43
24
|
class InspectorProxy {
|
|
44
|
-
// Root of the project used for relative to absolute source path conversion.
|
|
45
25
|
#projectRoot;
|
|
46
|
-
|
|
47
|
-
/** The base URL to the dev server from the developer machine. */
|
|
48
26
|
#serverBaseUrl;
|
|
49
|
-
|
|
50
|
-
// Maps device ID to Device instance.
|
|
51
27
|
#devices;
|
|
52
|
-
|
|
53
|
-
// Internal counter for device IDs -- just gets incremented for each new device.
|
|
54
28
|
#deviceCounter = 0;
|
|
55
29
|
#eventReporter;
|
|
56
30
|
#experiments;
|
|
57
|
-
|
|
58
|
-
// custom message handler factory allowing implementers to handle unsupported CDP messages.
|
|
59
31
|
#customMessageHandler;
|
|
60
32
|
constructor(
|
|
61
33
|
projectRoot,
|
|
@@ -72,7 +44,6 @@ class InspectorProxy {
|
|
|
72
44
|
this.#customMessageHandler = customMessageHandler;
|
|
73
45
|
}
|
|
74
46
|
getPageDescriptions() {
|
|
75
|
-
// Build list of pages from all devices.
|
|
76
47
|
let result = [];
|
|
77
48
|
Array.from(this.#devices.entries()).forEach(([deviceId, device]) => {
|
|
78
49
|
result = result.concat(
|
|
@@ -83,11 +54,6 @@ class InspectorProxy {
|
|
|
83
54
|
});
|
|
84
55
|
return result;
|
|
85
56
|
}
|
|
86
|
-
|
|
87
|
-
// Process HTTP request sent to server. We only respond to 2 HTTP requests:
|
|
88
|
-
// 1. /json/version returns Chrome debugger protocol version that we use
|
|
89
|
-
// 2. /json and /json/list returns list of page descriptions (list of inspectable apps).
|
|
90
|
-
// This list is combined from all the connected devices.
|
|
91
57
|
processRequest(request, response, next) {
|
|
92
58
|
const pathname = _url.default.parse(request.url).pathname;
|
|
93
59
|
if (
|
|
@@ -110,16 +76,10 @@ class InspectorProxy {
|
|
|
110
76
|
[WS_DEBUGGER_URL]: this.#createDebuggerConnectionWSServer(),
|
|
111
77
|
};
|
|
112
78
|
}
|
|
113
|
-
|
|
114
|
-
// Converts page information received from device into PageDescription object
|
|
115
|
-
// that is sent to debugger.
|
|
116
79
|
#buildPageDescription(deviceId, device, page) {
|
|
117
80
|
const { host, protocol } = new URL(this.#serverBaseUrl);
|
|
118
81
|
const webSocketScheme = protocol === "https:" ? "wss" : "ws";
|
|
119
82
|
const webSocketUrlWithoutProtocol = `${host}${WS_DEBUGGER_URL}?device=${deviceId}&page=${page.id}`;
|
|
120
|
-
// For now, `/json/list` returns the legacy built-in `devtools://` URL, to
|
|
121
|
-
// preserve existing handling by Flipper. This may return a placeholder in
|
|
122
|
-
// future -- please use the `/open-debugger` endpoint.
|
|
123
83
|
const devtoolsFrontendUrl =
|
|
124
84
|
`devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&${webSocketScheme}=` +
|
|
125
85
|
encodeURIComponent(webSocketUrlWithoutProtocol);
|
|
@@ -142,9 +102,6 @@ class InspectorProxy {
|
|
|
142
102
|
},
|
|
143
103
|
};
|
|
144
104
|
}
|
|
145
|
-
|
|
146
|
-
// Sends object as response to HTTP request.
|
|
147
|
-
// Just serializes object using JSON and sets required headers.
|
|
148
105
|
#sendJsonResponse(response, object) {
|
|
149
106
|
const data = JSON.stringify(object, null, 2);
|
|
150
107
|
response.writeHead(200, {
|
|
@@ -155,21 +112,12 @@ class InspectorProxy {
|
|
|
155
112
|
});
|
|
156
113
|
response.end(data);
|
|
157
114
|
}
|
|
158
|
-
|
|
159
|
-
// Adds websocket handler for device connections.
|
|
160
|
-
// Device connects to /inspector/device and passes device and app names as
|
|
161
|
-
// HTTP GET params.
|
|
162
|
-
// For each new websocket connection we parse device and app names and create
|
|
163
|
-
// new instance of Device class.
|
|
164
115
|
#createDeviceConnectionWSServer() {
|
|
165
116
|
const wss = new _ws.default.Server({
|
|
166
117
|
noServer: true,
|
|
167
118
|
perMessageDeflate: true,
|
|
168
|
-
// Don't crash on exceptionally large messages - assume the device is
|
|
169
|
-
// well-behaved and the debugger is prepared to handle large messages.
|
|
170
119
|
maxPayload: 0,
|
|
171
120
|
});
|
|
172
|
-
// $FlowFixMe[value-as-type]
|
|
173
121
|
wss.on("connection", async (socket, req) => {
|
|
174
122
|
try {
|
|
175
123
|
const fallbackDeviceId = String(this.#deviceCounter++);
|
|
@@ -178,24 +126,37 @@ class InspectorProxy {
|
|
|
178
126
|
const deviceName = query.name || "Unknown";
|
|
179
127
|
const appName = query.app || "Unknown";
|
|
180
128
|
const oldDevice = this.#devices.get(deviceId);
|
|
181
|
-
|
|
182
|
-
deviceId,
|
|
183
|
-
deviceName,
|
|
184
|
-
appName,
|
|
185
|
-
socket,
|
|
186
|
-
this.#projectRoot,
|
|
187
|
-
this.#eventReporter,
|
|
188
|
-
this.#customMessageHandler
|
|
189
|
-
);
|
|
129
|
+
let newDevice;
|
|
190
130
|
if (oldDevice) {
|
|
191
|
-
oldDevice.
|
|
131
|
+
oldDevice.dangerouslyRecreateDevice(
|
|
132
|
+
deviceId,
|
|
133
|
+
deviceName,
|
|
134
|
+
appName,
|
|
135
|
+
socket,
|
|
136
|
+
this.#projectRoot,
|
|
137
|
+
this.#eventReporter,
|
|
138
|
+
this.#customMessageHandler
|
|
139
|
+
);
|
|
140
|
+
newDevice = oldDevice;
|
|
141
|
+
} else {
|
|
142
|
+
newDevice = new _Device.default(
|
|
143
|
+
deviceId,
|
|
144
|
+
deviceName,
|
|
145
|
+
appName,
|
|
146
|
+
socket,
|
|
147
|
+
this.#projectRoot,
|
|
148
|
+
this.#eventReporter,
|
|
149
|
+
this.#customMessageHandler
|
|
150
|
+
);
|
|
192
151
|
}
|
|
193
152
|
this.#devices.set(deviceId, newDevice);
|
|
194
153
|
debug(
|
|
195
154
|
`Got new connection: name=${deviceName}, app=${appName}, device=${deviceId}`
|
|
196
155
|
);
|
|
197
156
|
socket.on("close", () => {
|
|
198
|
-
this.#devices.
|
|
157
|
+
if (this.#devices.get(deviceId)?.dangerouslyGetSocket() === socket) {
|
|
158
|
+
this.#devices.delete(deviceId);
|
|
159
|
+
}
|
|
199
160
|
debug(`Device ${deviceName} disconnected.`);
|
|
200
161
|
});
|
|
201
162
|
} catch (e) {
|
|
@@ -205,21 +166,12 @@ class InspectorProxy {
|
|
|
205
166
|
});
|
|
206
167
|
return wss;
|
|
207
168
|
}
|
|
208
|
-
|
|
209
|
-
// Returns websocket handler for debugger connections.
|
|
210
|
-
// Debugger connects to webSocketDebuggerUrl that we return as part of page description
|
|
211
|
-
// in /json response.
|
|
212
|
-
// When debugger connects we try to parse device and page IDs from the query and pass
|
|
213
|
-
// websocket object to corresponding Device instance.
|
|
214
169
|
#createDebuggerConnectionWSServer() {
|
|
215
170
|
const wss = new _ws.default.Server({
|
|
216
171
|
noServer: true,
|
|
217
172
|
perMessageDeflate: false,
|
|
218
|
-
// Don't crash on exceptionally large messages - assume the debugger is
|
|
219
|
-
// well-behaved and the device is prepared to handle large messages.
|
|
220
173
|
maxPayload: 0,
|
|
221
174
|
});
|
|
222
|
-
// $FlowFixMe[value-as-type]
|
|
223
175
|
wss.on("connection", async (socket, req) => {
|
|
224
176
|
try {
|
|
225
177
|
const query = _url.default.parse(req.url || "", true).query || {};
|
|
@@ -248,30 +200,17 @@ class InspectorProxy {
|
|
|
248
200
|
});
|
|
249
201
|
return wss;
|
|
250
202
|
}
|
|
251
|
-
|
|
252
|
-
// Starts pinging the socket at the given interval. Compliant clients will
|
|
253
|
-
// respond with pong frame. This serves both to detect when the client
|
|
254
|
-
// has gone away without sending a close frame, and as a keepalive in cases
|
|
255
|
-
// where proxies may drop idle connections (e.g., VS Code tunnels).
|
|
256
|
-
//
|
|
257
|
-
// https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2
|
|
258
203
|
#startHeartbeat(socket, intervalMs) {
|
|
259
204
|
let shouldSetTerminateTimeout = false;
|
|
260
205
|
let terminateTimeout = null;
|
|
261
206
|
const pingTimeout = (0, _timers.setTimeout)(() => {
|
|
262
207
|
if (socket.readyState !== _ws.default.OPEN) {
|
|
263
|
-
// May be connecting or closing, try again later.
|
|
264
208
|
pingTimeout.refresh();
|
|
265
209
|
return;
|
|
266
210
|
}
|
|
267
211
|
shouldSetTerminateTimeout = true;
|
|
268
212
|
socket.ping(() => {
|
|
269
213
|
if (!shouldSetTerminateTimeout) {
|
|
270
|
-
// Sometimes, this `sent` callback fires later than
|
|
271
|
-
// the actual pong reply.
|
|
272
|
-
//
|
|
273
|
-
// If any message came in between ping `sending` and `sent`,
|
|
274
|
-
// then the connection exists; and we don't need to do anything.
|
|
275
214
|
return;
|
|
276
215
|
}
|
|
277
216
|
shouldSetTerminateTimeout = false;
|
|
@@ -279,12 +218,6 @@ class InspectorProxy {
|
|
|
279
218
|
if (socket.readyState !== _ws.default.OPEN) {
|
|
280
219
|
return;
|
|
281
220
|
}
|
|
282
|
-
// We don't use close() here because that initiates a closing handshake,
|
|
283
|
-
// which will not complete if the other end has gone away - 'close'
|
|
284
|
-
// would not be emitted.
|
|
285
|
-
//
|
|
286
|
-
// terminate() emits 'close' immediately, allowing us to handle it and
|
|
287
|
-
// inform any clients.
|
|
288
221
|
socket.terminate();
|
|
289
222
|
}, MAX_PONG_LATENCY_MS).unref();
|
|
290
223
|
});
|
|
@@ -17,6 +17,10 @@ import type { IncomingMessage, ServerResponse } from "http";
|
|
|
17
17
|
import WS from "ws";
|
|
18
18
|
|
|
19
19
|
export interface InspectorProxyQueries {
|
|
20
|
+
/**
|
|
21
|
+
* Returns list of page descriptions ordered by device connection order, then
|
|
22
|
+
* page addition order.
|
|
23
|
+
*/
|
|
20
24
|
getPageDescriptions(): Array<PageDescription>;
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -9,24 +9,25 @@
|
|
|
9
9
|
* @oncall react_native
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import type { JSONSerializable } from "../types";
|
|
12
13
|
import type { Commands, Events } from "./protocol";
|
|
13
|
-
export type CDPEvent<TEvent extends keyof Events = "unknown"> =
|
|
14
|
+
export type CDPEvent<TEvent extends keyof Events = "unknown"> = {
|
|
14
15
|
method: TEvent;
|
|
15
16
|
params: Events[TEvent];
|
|
16
|
-
}
|
|
17
|
-
export type CDPRequest<TCommand extends keyof Commands = "unknown"> =
|
|
17
|
+
};
|
|
18
|
+
export type CDPRequest<TCommand extends keyof Commands = "unknown"> = {
|
|
18
19
|
method: TCommand;
|
|
19
20
|
params: Commands[TCommand]["paramsType"];
|
|
20
21
|
id: number;
|
|
21
|
-
}
|
|
22
|
+
};
|
|
22
23
|
export type CDPResponse<TCommand extends keyof Commands = "unknown"> =
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
export type CDPRequestError =
|
|
24
|
+
| { result: Commands[TCommand]["resultType"]; id: number }
|
|
25
|
+
| { error: CDPRequestError; id: number };
|
|
26
|
+
export type CDPRequestError = {
|
|
26
27
|
code: number;
|
|
27
28
|
message: string;
|
|
28
|
-
data?:
|
|
29
|
-
}
|
|
29
|
+
data?: JSONSerializable;
|
|
30
|
+
};
|
|
30
31
|
export type CDPClientMessage =
|
|
31
32
|
| CDPRequest<"Debugger.getScriptSource">
|
|
32
33
|
| CDPRequest<"Debugger.scriptParsed">
|
|
@@ -9,35 +9,36 @@
|
|
|
9
9
|
* @oncall react_native
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import type { JSONSerializable } from "../types";
|
|
12
13
|
import type { Commands, Events } from "./protocol";
|
|
13
14
|
|
|
14
15
|
// Note: A CDP event is a JSON-RPC notification with no `id` member.
|
|
15
|
-
export type CDPEvent<TEvent: $Keys<Events> = "unknown"> =
|
|
16
|
+
export type CDPEvent<TEvent: $Keys<Events> = "unknown"> = {
|
|
16
17
|
method: TEvent,
|
|
17
18
|
params: Events[TEvent],
|
|
18
|
-
}
|
|
19
|
+
};
|
|
19
20
|
|
|
20
|
-
export type CDPRequest<TCommand: $Keys<Commands> = "unknown"> =
|
|
21
|
+
export type CDPRequest<TCommand: $Keys<Commands> = "unknown"> = {
|
|
21
22
|
method: TCommand,
|
|
22
23
|
params: Commands[TCommand]["paramsType"],
|
|
23
24
|
id: number,
|
|
24
|
-
}
|
|
25
|
+
};
|
|
25
26
|
|
|
26
27
|
export type CDPResponse<TCommand: $Keys<Commands> = "unknown"> =
|
|
27
|
-
|
|
|
28
|
+
| {
|
|
28
29
|
result: Commands[TCommand]["resultType"],
|
|
29
30
|
id: number,
|
|
30
|
-
}
|
|
31
|
-
|
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
32
33
|
error: CDPRequestError,
|
|
33
34
|
id: number,
|
|
34
|
-
}
|
|
35
|
+
};
|
|
35
36
|
|
|
36
|
-
export type CDPRequestError =
|
|
37
|
+
export type CDPRequestError = {
|
|
37
38
|
code: number,
|
|
38
39
|
message: string,
|
|
39
|
-
data?:
|
|
40
|
-
}
|
|
40
|
+
data?: JSONSerializable,
|
|
41
|
+
};
|
|
41
42
|
|
|
42
43
|
export type CDPClientMessage =
|
|
43
44
|
| CDPRequest<"Debugger.getScriptSource">
|
|
@@ -9,15 +9,16 @@
|
|
|
9
9
|
* @oncall react_native
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import type { JSONSerializable } from "../types";
|
|
12
13
|
type integer = number;
|
|
13
14
|
export interface Debugger {
|
|
14
|
-
GetScriptSourceParams:
|
|
15
|
+
GetScriptSourceParams: {
|
|
15
16
|
/**
|
|
16
17
|
* Id of the script to get source for.
|
|
17
18
|
*/
|
|
18
19
|
scriptId: string;
|
|
19
|
-
}
|
|
20
|
-
GetScriptSourceResult:
|
|
20
|
+
};
|
|
21
|
+
GetScriptSourceResult: {
|
|
21
22
|
/**
|
|
22
23
|
* Script source (empty in case of Wasm bytecode).
|
|
23
24
|
*/
|
|
@@ -26,8 +27,8 @@ export interface Debugger {
|
|
|
26
27
|
* Wasm bytecode. (Encoded as a base64 string when passed over JSON)
|
|
27
28
|
*/
|
|
28
29
|
bytecode?: string;
|
|
29
|
-
}
|
|
30
|
-
SetBreakpointByUrlParams:
|
|
30
|
+
};
|
|
31
|
+
SetBreakpointByUrlParams: {
|
|
31
32
|
/**
|
|
32
33
|
* Line number to set breakpoint at.
|
|
33
34
|
*/
|
|
@@ -54,8 +55,8 @@ export interface Debugger {
|
|
|
54
55
|
* breakpoint if this expression evaluates to true.
|
|
55
56
|
*/
|
|
56
57
|
condition?: string;
|
|
57
|
-
}
|
|
58
|
-
ScriptParsedEvent:
|
|
58
|
+
};
|
|
59
|
+
ScriptParsedEvent: {
|
|
59
60
|
/**
|
|
60
61
|
* Identifier of the script parsed.
|
|
61
62
|
*/
|
|
@@ -68,11 +69,11 @@ export interface Debugger {
|
|
|
68
69
|
* URL of source map associated with script (if any).
|
|
69
70
|
*/
|
|
70
71
|
sourceMapURL: string;
|
|
71
|
-
}
|
|
72
|
+
};
|
|
72
73
|
}
|
|
73
74
|
export type Events = {
|
|
74
75
|
"Debugger.scriptParsed": Debugger["ScriptParsedEvent"];
|
|
75
|
-
[method: string]:
|
|
76
|
+
[method: string]: JSONSerializable;
|
|
76
77
|
};
|
|
77
78
|
export type Commands = {
|
|
78
79
|
"Debugger.getScriptSource": {
|
|
@@ -83,5 +84,8 @@ export type Commands = {
|
|
|
83
84
|
paramsType: Debugger["SetBreakpointByUrlParams"];
|
|
84
85
|
resultType: void;
|
|
85
86
|
};
|
|
86
|
-
[method: string]: {
|
|
87
|
+
[method: string]: {
|
|
88
|
+
paramsType: JSONSerializable;
|
|
89
|
+
resultType: JSONSerializable;
|
|
90
|
+
};
|
|
87
91
|
};
|
|
@@ -11,17 +11,19 @@
|
|
|
11
11
|
|
|
12
12
|
// Adapted from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts
|
|
13
13
|
|
|
14
|
+
import type { JSONSerializable } from "../types";
|
|
15
|
+
|
|
14
16
|
type integer = number;
|
|
15
17
|
|
|
16
18
|
export interface Debugger {
|
|
17
|
-
GetScriptSourceParams:
|
|
19
|
+
GetScriptSourceParams: {
|
|
18
20
|
/**
|
|
19
21
|
* Id of the script to get source for.
|
|
20
22
|
*/
|
|
21
23
|
scriptId: string,
|
|
22
|
-
}
|
|
24
|
+
};
|
|
23
25
|
|
|
24
|
-
GetScriptSourceResult:
|
|
26
|
+
GetScriptSourceResult: {
|
|
25
27
|
/**
|
|
26
28
|
* Script source (empty in case of Wasm bytecode).
|
|
27
29
|
*/
|
|
@@ -31,9 +33,9 @@ export interface Debugger {
|
|
|
31
33
|
* Wasm bytecode. (Encoded as a base64 string when passed over JSON)
|
|
32
34
|
*/
|
|
33
35
|
bytecode?: string,
|
|
34
|
-
}
|
|
36
|
+
};
|
|
35
37
|
|
|
36
|
-
SetBreakpointByUrlParams:
|
|
38
|
+
SetBreakpointByUrlParams: {
|
|
37
39
|
/**
|
|
38
40
|
* Line number to set breakpoint at.
|
|
39
41
|
*/
|
|
@@ -65,9 +67,9 @@ export interface Debugger {
|
|
|
65
67
|
* breakpoint if this expression evaluates to true.
|
|
66
68
|
*/
|
|
67
69
|
condition?: string,
|
|
68
|
-
}
|
|
70
|
+
};
|
|
69
71
|
|
|
70
|
-
ScriptParsedEvent:
|
|
72
|
+
ScriptParsedEvent: {
|
|
71
73
|
/**
|
|
72
74
|
* Identifier of the script parsed.
|
|
73
75
|
*/
|
|
@@ -82,12 +84,12 @@ export interface Debugger {
|
|
|
82
84
|
* URL of source map associated with script (if any).
|
|
83
85
|
*/
|
|
84
86
|
sourceMapURL: string,
|
|
85
|
-
}
|
|
87
|
+
};
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
export type Events = {
|
|
89
91
|
"Debugger.scriptParsed": Debugger["ScriptParsedEvent"],
|
|
90
|
-
[method: string]:
|
|
92
|
+
[method: string]: JSONSerializable,
|
|
91
93
|
};
|
|
92
94
|
|
|
93
95
|
export type Commands = {
|
|
@@ -100,7 +102,7 @@ export type Commands = {
|
|
|
100
102
|
resultType: void,
|
|
101
103
|
},
|
|
102
104
|
[method: string]: {
|
|
103
|
-
paramsType:
|
|
104
|
-
resultType:
|
|
105
|
+
paramsType: JSONSerializable,
|
|
106
|
+
resultType: JSONSerializable,
|
|
105
107
|
},
|
|
106
108
|
};
|
|
@@ -109,3 +109,9 @@ export type JSONSerializable =
|
|
|
109
109
|
| null
|
|
110
110
|
| ReadonlyArray<JSONSerializable>
|
|
111
111
|
| { readonly [$$Key$$: string]: JSONSerializable };
|
|
112
|
+
export type DeepReadOnly<T> =
|
|
113
|
+
T extends ReadonlyArray<infer V>
|
|
114
|
+
? ReadonlyArray<DeepReadOnly<V>>
|
|
115
|
+
: T extends {}
|
|
116
|
+
? { readonly [K in keyof T]: DeepReadOnly<T[K]> }
|
|
117
|
+
: T;
|
|
@@ -146,3 +146,10 @@ export type JSONSerializable =
|
|
|
146
146
|
| null
|
|
147
147
|
| $ReadOnlyArray<JSONSerializable>
|
|
148
148
|
| { +[string]: JSONSerializable };
|
|
149
|
+
|
|
150
|
+
export type DeepReadOnly<T> =
|
|
151
|
+
T extends $ReadOnlyArray<infer V>
|
|
152
|
+
? $ReadOnlyArray<DeepReadOnly<V>>
|
|
153
|
+
: T extends { ... }
|
|
154
|
+
? { +[K in keyof T]: DeepReadOnly<T[K]> }
|
|
155
|
+
: T;
|
|
@@ -8,26 +8,8 @@ var _open = _interopRequireDefault(require("open"));
|
|
|
8
8
|
function _interopRequireDefault(obj) {
|
|
9
9
|
return obj && obj.__esModule ? obj : { default: obj };
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
13
|
-
*
|
|
14
|
-
* This source code is licensed under the MIT license found in the
|
|
15
|
-
* LICENSE file in the root directory of this source tree.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @format
|
|
19
|
-
* @oncall react_native
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
11
|
const FLIPPER_SELF_CONNECT_URL =
|
|
23
12
|
"flipper://null/Hermesdebuggerrn?device=React%20Native";
|
|
24
|
-
/**
|
|
25
|
-
* Open the legacy Flipper debugger (Hermes).
|
|
26
|
-
*
|
|
27
|
-
* @deprecated This replicates the pre-0.73 workflow of opening Flipper via the
|
|
28
|
-
* `flipper://` URL scheme, failing if Flipper is not installed locally. This
|
|
29
|
-
* flow will be removed in a future version.
|
|
30
|
-
*/
|
|
31
13
|
function deprecated_openFlipperMiddleware({ logger }) {
|
|
32
14
|
return async (req, res, next) => {
|
|
33
15
|
if (req.method === "POST") {
|
|
@@ -11,25 +11,6 @@ var _url = _interopRequireDefault(require("url"));
|
|
|
11
11
|
function _interopRequireDefault(obj) {
|
|
12
12
|
return obj && obj.__esModule ? obj : { default: obj };
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
16
|
-
*
|
|
17
|
-
* This source code is licensed under the MIT license found in the
|
|
18
|
-
* LICENSE file in the root directory of this source tree.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @format
|
|
22
|
-
* @oncall react_native
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Open the JavaScript debugger for a given CDP target (direct Hermes debugging).
|
|
27
|
-
*
|
|
28
|
-
* Currently supports Hermes targets, opening debugger websocket URL in Chrome
|
|
29
|
-
* DevTools.
|
|
30
|
-
*
|
|
31
|
-
* @see https://chromedevtools.github.io/devtools-protocol/
|
|
32
|
-
*/
|
|
33
14
|
function openDebuggerMiddleware({
|
|
34
15
|
serverBaseUrl,
|
|
35
16
|
logger,
|
|
@@ -44,34 +25,40 @@ function openDebuggerMiddleware({
|
|
|
44
25
|
(experiments.enableOpenDebuggerRedirect && req.method === "GET")
|
|
45
26
|
) {
|
|
46
27
|
const { query } = _url.default.parse(req.url, true);
|
|
47
|
-
const { appId, device, launchId } = query;
|
|
48
|
-
const targets = inspectorProxy
|
|
49
|
-
|
|
50
|
-
(
|
|
51
|
-
app
|
|
52
|
-
|
|
53
|
-
|
|
28
|
+
const { appId, device, launchId, target: targetId } = query;
|
|
29
|
+
const targets = inspectorProxy
|
|
30
|
+
.getPageDescriptions()
|
|
31
|
+
.filter(
|
|
32
|
+
(app) =>
|
|
33
|
+
app.title ===
|
|
34
|
+
"React Native Experimental (Improved Chrome Reloads)" ||
|
|
35
|
+
app.reactNative.capabilities?.nativePageReloads === true
|
|
36
|
+
);
|
|
54
37
|
let target;
|
|
55
38
|
const launchType = req.method === "POST" ? "launch" : "redirect";
|
|
56
|
-
if (
|
|
39
|
+
if (
|
|
40
|
+
typeof targetId === "string" ||
|
|
41
|
+
typeof appId === "string" ||
|
|
42
|
+
typeof device === "string"
|
|
43
|
+
) {
|
|
57
44
|
logger?.info(
|
|
58
45
|
(launchType === "launch" ? "Launching" : "Redirecting to") +
|
|
59
46
|
" JS debugger (experimental)..."
|
|
60
47
|
);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
48
|
+
target = targets.find(
|
|
49
|
+
(_target) =>
|
|
50
|
+
(targetId == null || _target.id === targetId) &&
|
|
51
|
+
(appId == null || _target.description === appId) &&
|
|
52
|
+
(device == null || _target.reactNative.logicalDeviceId === device)
|
|
53
|
+
);
|
|
54
|
+
} else if (targets.length > 0) {
|
|
70
55
|
logger?.info(
|
|
71
56
|
(launchType === "launch" ? "Launching" : "Redirecting to") +
|
|
72
|
-
|
|
57
|
+
` JS debugger${
|
|
58
|
+
targets.length === 1 ? "" : " for most recently connected target"
|
|
59
|
+
}...`
|
|
73
60
|
);
|
|
74
|
-
target = targets[
|
|
61
|
+
target = targets[targets.length - 1];
|
|
75
62
|
}
|
|
76
63
|
if (!target) {
|
|
77
64
|
res.writeHead(404);
|