@react-native/dev-middleware 0.74.0-nightly-20240205-e4342f5b0 → 0.74.0-nightly-20240206-bc3fe0d76

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.
@@ -105,7 +105,7 @@ class Device {
105
105
  #lastConnectedLegacyReactNativePage = null;
106
106
 
107
107
  // Whether we are in the middle of a reload in the REACT_NATIVE_RELOADABLE_PAGE.
108
- #isReloading = false;
108
+ #isLegacyPageReloading = false;
109
109
 
110
110
  // The previous "GetPages" message, for deduplication in debug logs.
111
111
  #lastGetPagesMessage = "";
@@ -180,7 +180,7 @@ class Device {
180
180
  title: "React Native Experimental (Improved Chrome Reloads)",
181
181
  vm: "don't use",
182
182
  app: this.#app,
183
- type: "Legacy",
183
+ capabilities: {},
184
184
  };
185
185
  return [...this.#pages.values(), reactNativeReloadablePage];
186
186
  } else {
@@ -233,8 +233,8 @@ class Device {
233
233
  frontendUserAgent: metadata.userAgent,
234
234
  });
235
235
  let processedReq = debuggerRequest;
236
- if (!page || page.type === "Legacy") {
237
- processedReq = this.#interceptMessageFromDebuggerLegacy(
236
+ if (!page || !this.#pageHasCapability(page, "nativeSourceCodeFetching")) {
237
+ processedReq = this.#interceptClientMessageForSourceFetching(
238
238
  debuggerRequest,
239
239
  debuggerInfo,
240
240
  socket
@@ -303,6 +303,13 @@ class Device {
303
303
  }
304
304
  }
305
305
 
306
+ /**
307
+ * Returns `true` if a page supports the given target capability flag.
308
+ */
309
+ #pageHasCapability(page, flag) {
310
+ return page.capabilities[flag] === true;
311
+ }
312
+
306
313
  // Handles messages received from device:
307
314
  // 1. For getPages responses updates local #pages list.
308
315
  // 2. All other messages are forwarded to debugger as wrappedEvent.
@@ -313,11 +320,11 @@ class Device {
313
320
  #handleMessageFromDevice(message) {
314
321
  if (message.event === "getPages") {
315
322
  this.#pages = new Map(
316
- message.payload.map(({ type, ...page }) => [
323
+ message.payload.map(({ capabilities, ...page }) => [
317
324
  page.id,
318
325
  {
319
326
  ...page,
320
- type: type ?? "Legacy",
327
+ capabilities: capabilities ?? {},
321
328
  },
322
329
  ])
323
330
  );
@@ -344,7 +351,10 @@ class Device {
344
351
  // TODO(hypuk): It is better for VM to send update event when new page is
345
352
  // created instead of manually checking this on every getPages result.
346
353
  for (const page of this.#pages.values()) {
347
- if (page.type === "Legacy" && page.title.indexOf("React") >= 0) {
354
+ if (this.#pageHasCapability(page, "nativePageReloads")) {
355
+ continue;
356
+ }
357
+ if (page.title.includes("React")) {
348
358
  if (page.id !== this.#lastConnectedLegacyReactNativePage?.id) {
349
359
  this.#newLegacyReactNativePage(page);
350
360
  break;
@@ -358,14 +368,16 @@ class Device {
358
368
  // TODO(moti): Handle null case explicitly, e.g. swallow disconnect events
359
369
  // for unknown pages.
360
370
  const page = this.#pages.get(pageId);
371
+ if (page != null && this.#pageHasCapability(page, "nativePageReloads")) {
372
+ return;
373
+ }
361
374
  const debuggerSocket = this.#debuggerConnection
362
375
  ? this.#debuggerConnection.socket
363
376
  : null;
364
377
  if (debuggerSocket && debuggerSocket.readyState === _ws.default.OPEN) {
365
378
  if (
366
379
  this.#debuggerConnection != null &&
367
- this.#debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID &&
368
- (!page || page.type === "Legacy")
380
+ this.#debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID
369
381
  ) {
370
382
  debug(`Legacy page ${pageId} is reloading.`);
371
383
  debuggerSocket.send(
@@ -394,22 +406,19 @@ class Device {
394
406
  }
395
407
  const parsedPayload = JSON.parse(message.payload.wrappedEvent);
396
408
  const pageId = this.#debuggerConnection?.pageId ?? null;
397
- // TODO(moti): Handle null case explicitly, or ideally associate a copy
398
- // of the page metadata object with the connection so this can never be
399
- // null.
400
- const page = pageId != null ? this.#pages.get(pageId) : null;
401
409
  if ("id" in parsedPayload) {
402
410
  this.#deviceEventReporter?.logResponse(parsedPayload, "device", {
403
411
  pageId,
404
412
  frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
405
413
  });
406
414
  }
407
- if (this.#debuggerConnection && (!page || page.type === "Legacy")) {
415
+ if (this.#debuggerConnection != null) {
408
416
  // Wrapping just to make flow happy :)
409
417
  // $FlowFixMe[unused-promise]
410
418
  this.#processMessageFromDeviceLegacy(
411
419
  parsedPayload,
412
- this.#debuggerConnection
420
+ this.#debuggerConnection,
421
+ pageId
413
422
  ).then(() => {
414
423
  const messageToSend = JSON.stringify(parsedPayload);
415
424
  debuggerSocket.send(messageToSend);
@@ -445,7 +454,7 @@ class Device {
445
454
  }
446
455
  const oldPageId = this.#lastConnectedLegacyReactNativePage?.id;
447
456
  this.#lastConnectedLegacyReactNativePage = page;
448
- this.#isReloading = true;
457
+ this.#isLegacyPageReloading = true;
449
458
 
450
459
  // We already had a debugger connected to React Native page and a
451
460
  // new one appeared - in this case we need to emulate execution context
@@ -492,14 +501,24 @@ class Device {
492
501
  }
493
502
 
494
503
  // Allows to make changes in incoming message from device.
495
- async #processMessageFromDeviceLegacy(payload, debuggerInfo) {
504
+ async #processMessageFromDeviceLegacy(payload, debuggerInfo, pageId) {
505
+ // TODO(moti): Handle null case explicitly, or ideally associate a copy
506
+ // of the page metadata object with the connection so this can never be
507
+ // null.
508
+ const page = pageId != null ? this.#pages.get(pageId) : null;
509
+
496
510
  // Replace Android addresses for scriptParsed event.
497
- if (payload.method === "Debugger.scriptParsed") {
498
- const params = payload.params || {};
511
+ if (
512
+ (!page || !this.#pageHasCapability(page, "nativeSourceCodeFetching")) &&
513
+ payload.method === "Debugger.scriptParsed" &&
514
+ payload.params != null
515
+ ) {
516
+ const params = payload.params;
499
517
  if ("sourceMapURL" in params) {
500
518
  for (let i = 0; i < EMULATOR_LOCALHOST_ADDRESSES.length; ++i) {
501
519
  const address = EMULATOR_LOCALHOST_ADDRESSES[i];
502
- if (params.sourceMapURL.indexOf(address) >= 0) {
520
+ if (params.sourceMapURL.includes(address)) {
521
+ // $FlowFixMe[cannot-write]
503
522
  payload.params.sourceMapURL = params.sourceMapURL.replace(
504
523
  address,
505
524
  "localhost"
@@ -516,6 +535,7 @@ class Device {
516
535
  // message to the debug client.
517
536
  try {
518
537
  const sourceMap = await this.#fetchText(sourceMapURL);
538
+ // $FlowFixMe[cannot-write]
519
539
  payload.params.sourceMapURL =
520
540
  "data:application/json;charset=utf-8;base64," +
521
541
  new Buffer(sourceMap).toString("base64");
@@ -530,6 +550,7 @@ class Device {
530
550
  for (let i = 0; i < EMULATOR_LOCALHOST_ADDRESSES.length; ++i) {
531
551
  const address = EMULATOR_LOCALHOST_ADDRESSES[i];
532
552
  if (params.url.indexOf(address) >= 0) {
553
+ // $FlowFixMe[cannot-write]
533
554
  payload.params.url = params.url.replace(address, "localhost");
534
555
  debuggerInfo.originalSourceURLAddress = address;
535
556
  }
@@ -540,6 +561,7 @@ class Device {
540
561
  // Chrome to not download source maps. In this case we want to prepend script ID
541
562
  // with 'file://' prefix.
542
563
  if (payload.params.url.match(/^[0-9a-z]+$/)) {
564
+ // $FlowFixMe[cannot-write]
543
565
  payload.params.url = FILE_PREFIX + payload.params.url;
544
566
  debuggerInfo.prependedFilePrefix = true;
545
567
  }
@@ -552,7 +574,7 @@ class Device {
552
574
  }
553
575
  if (
554
576
  payload.method === "Runtime.executionContextCreated" &&
555
- this.#isReloading
577
+ this.#isLegacyPageReloading
556
578
  ) {
557
579
  // The new context is ready. First notify Chrome that we've reloaded so
558
580
  // it'll resend its breakpoints. If we do this earlier, we may not be
@@ -585,21 +607,26 @@ class Device {
585
607
  wrappedEvent: JSON.stringify(resumeMessage),
586
608
  },
587
609
  });
588
- this.#isReloading = false;
610
+ this.#isLegacyPageReloading = false;
589
611
  }
590
612
  }
591
613
 
592
- // Allows to make changes in incoming messages from debugger. Returns a boolean
593
- // indicating whether the message has been handled locally (i.e. does not need
594
- // to be forwarded to the target).
595
- #interceptMessageFromDebuggerLegacy(req, debuggerInfo, socket) {
596
- if (req.method === "Debugger.setBreakpointByUrl") {
597
- return this.#processDebuggerSetBreakpointByUrl(req, debuggerInfo);
598
- } else if (req.method === "Debugger.getScriptSource") {
599
- this.#processDebuggerGetScriptSource(req, socket);
600
- return null;
614
+ /**
615
+ * Intercept an incoming message from a connected debugger. Returns either an
616
+ * original/replacement CDP message object, or `null` (will forward nothing
617
+ * to the target).
618
+ */
619
+ #interceptClientMessageForSourceFetching(req, debuggerInfo, socket) {
620
+ switch (req.method) {
621
+ case "Debugger.setBreakpointByUrl":
622
+ return this.#processDebuggerSetBreakpointByUrl(req, debuggerInfo);
623
+ case "Debugger.getScriptSource":
624
+ // Sends response to debugger via side-effect
625
+ this.#processDebuggerGetScriptSource(req, socket);
626
+ return null;
627
+ default:
628
+ return req;
601
629
  }
602
- return req;
603
630
  }
604
631
  #processDebuggerSetBreakpointByUrl(req, debuggerInfo) {
605
632
  // If we replaced Android emulator's address to localhost we need to change it back.
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import type { EventReporter } from "../types/EventReporter";
12
+ import type { CDPResponse } from "./cdp-types/messages";
12
13
  type DeviceMetadata = Readonly<{
13
14
  appId: string;
14
15
  deviceId: string;
@@ -26,7 +27,7 @@ declare class DeviceEventReporter {
26
27
  metadata: RequestMetadata
27
28
  ): void;
28
29
  logResponse(
29
- res: Readonly<{ id: number; error?: { message: string; data?: unknown } }>,
30
+ res: CDPResponse<>,
30
31
  origin: "device" | "proxy",
31
32
  metadata: Readonly<{
32
33
  pageId: string | null;
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import type { EventReporter } from "../types/EventReporter";
12
+ import type { CDPResponse } from "./cdp-types/messages";
12
13
 
13
14
  type DeviceMetadata = $ReadOnly<{
14
15
  appId: string,
@@ -29,11 +30,7 @@ declare class DeviceEventReporter {
29
30
  metadata: RequestMetadata
30
31
  ): void;
31
32
  logResponse(
32
- res: $ReadOnly<{
33
- id: number,
34
- error?: { message: string, data?: mixed },
35
- ...
36
- }>,
33
+ res: CDPResponse<>,
37
34
  origin: "device" | "proxy",
38
35
  metadata: $ReadOnly<{
39
36
  pageId: string | null,
@@ -117,7 +117,7 @@ class InspectorProxy {
117
117
  deviceName: device.getName(),
118
118
  reactNative: {
119
119
  logicalDeviceId: deviceId,
120
- type: (0, _nullthrows.default)(page.type),
120
+ capabilities: (0, _nullthrows.default)(page.capabilities),
121
121
  },
122
122
  };
123
123
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type { Commands, Events } from "./protocol";
13
+ export type CDPEvent<TEvent extends keyof Events = "unknown"> = Readonly<{
14
+ method: TEvent;
15
+ params: Events[TEvent];
16
+ }>;
17
+ export type CDPRequest<TCommand extends keyof Commands = "unknown"> = Readonly<{
18
+ method: TCommand;
19
+ params: Commands[TCommand]["paramsType"];
20
+ id: number;
21
+ }>;
22
+ export type CDPResponse<TCommand extends keyof Commands = "unknown"> =
23
+ | Readonly<{ result: Commands[TCommand]["resultType"]; id: number }>
24
+ | Readonly<{ error: CDPRequestError; id: number }>;
25
+ export type CDPRequestError = Readonly<{
26
+ code: number;
27
+ message: string;
28
+ data?: unknown;
29
+ }>;
30
+ export type CDPClientMessage =
31
+ | CDPRequest<"Debugger.getScriptSource">
32
+ | CDPRequest<"Debugger.scriptParsed">
33
+ | CDPRequest<"Debugger.setBreakpointByUrl">
34
+ | CDPRequest<>;
35
+ export type CDPServerMessage =
36
+ | CDPEvent<"Debugger.scriptParsed">
37
+ | CDPEvent<>
38
+ | CDPResponse<"Debugger.getScriptSource">
39
+ | CDPResponse<>;
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type { Commands, Events } from "./protocol";
13
+
14
+ // Note: A CDP event is a JSON-RPC notification with no `id` member.
15
+ export type CDPEvent<TEvent: $Keys<Events> = "unknown"> = $ReadOnly<{
16
+ method: TEvent,
17
+ params: Events[TEvent],
18
+ }>;
19
+
20
+ export type CDPRequest<TCommand: $Keys<Commands> = "unknown"> = $ReadOnly<{
21
+ method: TCommand,
22
+ params: Commands[TCommand]["paramsType"],
23
+ id: number,
24
+ }>;
25
+
26
+ export type CDPResponse<TCommand: $Keys<Commands> = "unknown"> =
27
+ | $ReadOnly<{
28
+ result: Commands[TCommand]["resultType"],
29
+ id: number,
30
+ }>
31
+ | $ReadOnly<{
32
+ error: CDPRequestError,
33
+ id: number,
34
+ }>;
35
+
36
+ export type CDPRequestError = $ReadOnly<{
37
+ code: number,
38
+ message: string,
39
+ data?: mixed,
40
+ }>;
41
+
42
+ export type CDPClientMessage =
43
+ | CDPRequest<"Debugger.getScriptSource">
44
+ | CDPRequest<"Debugger.scriptParsed">
45
+ | CDPRequest<"Debugger.setBreakpointByUrl">
46
+ | CDPRequest<>;
47
+
48
+ export type CDPServerMessage =
49
+ | CDPEvent<"Debugger.scriptParsed">
50
+ | CDPEvent<>
51
+ | CDPResponse<"Debugger.getScriptSource">
52
+ | CDPResponse<>;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ type integer = number;
13
+ export interface Debugger {
14
+ GetScriptSourceParams: Readonly<{
15
+ /**
16
+ * Id of the script to get source for.
17
+ */
18
+ scriptId: string;
19
+ }>;
20
+ GetScriptSourceResult: Readonly<{
21
+ /**
22
+ * Script source (empty in case of Wasm bytecode).
23
+ */
24
+ scriptSource: string;
25
+ /**
26
+ * Wasm bytecode. (Encoded as a base64 string when passed over JSON)
27
+ */
28
+ bytecode?: string;
29
+ }>;
30
+ SetBreakpointByUrlParams: Readonly<{
31
+ /**
32
+ * Line number to set breakpoint at.
33
+ */
34
+ lineNumber: integer;
35
+ /**
36
+ * URL of the resources to set breakpoint on.
37
+ */
38
+ url?: string;
39
+ /**
40
+ * Regex pattern for the URLs of the resources to set breakpoints on. Either `url` or
41
+ * `urlRegex` must be specified.
42
+ */
43
+ urlRegex?: string;
44
+ /**
45
+ * Script hash of the resources to set breakpoint on.
46
+ */
47
+ scriptHash?: string;
48
+ /**
49
+ * Offset in the line to set breakpoint at.
50
+ */
51
+ columnNumber?: integer;
52
+ /**
53
+ * Expression to use as a breakpoint condition. When specified, debugger will only stop on the
54
+ * breakpoint if this expression evaluates to true.
55
+ */
56
+ condition?: string;
57
+ }>;
58
+ ScriptParsedEvent: Readonly<{
59
+ /**
60
+ * Identifier of the script parsed.
61
+ */
62
+ scriptId: string;
63
+ /**
64
+ * URL or name of the script parsed (if any).
65
+ */
66
+ url: string;
67
+ /**
68
+ * URL of source map associated with script (if any).
69
+ */
70
+ sourceMapURL: string;
71
+ }>;
72
+ }
73
+ export type Events = {
74
+ "Debugger.scriptParsed": Debugger["ScriptParsedEvent"];
75
+ [method: string]: unknown;
76
+ };
77
+ export type Commands = {
78
+ "Debugger.getScriptSource": {
79
+ paramsType: Debugger["GetScriptSourceParams"];
80
+ resultType: Debugger["GetScriptSourceResult"];
81
+ };
82
+ "Debugger.setBreakpointByUrl": {
83
+ paramsType: Debugger["SetBreakpointByUrlParams"];
84
+ resultType: void;
85
+ };
86
+ [method: string]: { paramsType: unknown; resultType: unknown };
87
+ };
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ // Adapted from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts
13
+
14
+ type integer = number;
15
+
16
+ export interface Debugger {
17
+ GetScriptSourceParams: $ReadOnly<{
18
+ /**
19
+ * Id of the script to get source for.
20
+ */
21
+ scriptId: string,
22
+ }>;
23
+
24
+ GetScriptSourceResult: $ReadOnly<{
25
+ /**
26
+ * Script source (empty in case of Wasm bytecode).
27
+ */
28
+ scriptSource: string,
29
+
30
+ /**
31
+ * Wasm bytecode. (Encoded as a base64 string when passed over JSON)
32
+ */
33
+ bytecode?: string,
34
+ }>;
35
+
36
+ SetBreakpointByUrlParams: $ReadOnly<{
37
+ /**
38
+ * Line number to set breakpoint at.
39
+ */
40
+ lineNumber: integer,
41
+
42
+ /**
43
+ * URL of the resources to set breakpoint on.
44
+ */
45
+ url?: string,
46
+
47
+ /**
48
+ * Regex pattern for the URLs of the resources to set breakpoints on. Either `url` or
49
+ * `urlRegex` must be specified.
50
+ */
51
+ urlRegex?: string,
52
+
53
+ /**
54
+ * Script hash of the resources to set breakpoint on.
55
+ */
56
+ scriptHash?: string,
57
+
58
+ /**
59
+ * Offset in the line to set breakpoint at.
60
+ */
61
+ columnNumber?: integer,
62
+
63
+ /**
64
+ * Expression to use as a breakpoint condition. When specified, debugger will only stop on the
65
+ * breakpoint if this expression evaluates to true.
66
+ */
67
+ condition?: string,
68
+ }>;
69
+
70
+ ScriptParsedEvent: $ReadOnly<{
71
+ /**
72
+ * Identifier of the script parsed.
73
+ */
74
+ scriptId: string,
75
+
76
+ /**
77
+ * URL or name of the script parsed (if any).
78
+ */
79
+ url: string,
80
+
81
+ /**
82
+ * URL of source map associated with script (if any).
83
+ */
84
+ sourceMapURL: string,
85
+ }>;
86
+ }
87
+
88
+ export type Events = {
89
+ "Debugger.scriptParsed": Debugger["ScriptParsedEvent"],
90
+ [method: string]: mixed,
91
+ };
92
+
93
+ export type Commands = {
94
+ "Debugger.getScriptSource": {
95
+ paramsType: Debugger["GetScriptSourceParams"],
96
+ resultType: Debugger["GetScriptSourceResult"],
97
+ },
98
+ "Debugger.setBreakpointByUrl": {
99
+ paramsType: Debugger["SetBreakpointByUrlParams"],
100
+ resultType: void,
101
+ },
102
+ [method: string]: {
103
+ paramsType: mixed,
104
+ resultType: mixed,
105
+ },
106
+ };
@@ -9,12 +9,33 @@
9
9
  * @oncall react_native
10
10
  */
11
11
 
12
+ /**
13
+ * A capability flag disables a specific feature/hack in the InspectorProxy
14
+ * layer by indicating that the target supports one or more modern CDP features.
15
+ */
16
+ export type TargetCapabilityFlags = Readonly<{
17
+ /**
18
+ * The target supports a stable page representation across reloads.
19
+ *
20
+ * In the proxy, this disables legacy page reload emulation and the
21
+ * additional '(Experimental)' target in `/json/list`.
22
+ *
23
+ * In the launch flow, this allows targets to be matched directly by `appId`.
24
+ */
25
+ nativePageReloads?: boolean;
26
+ /**
27
+ * The target supports fetching source code and source maps.
28
+ *
29
+ * In the proxy, this disables source fetching emulation and host rewrites.
30
+ */
31
+ nativeSourceCodeFetching?: boolean;
32
+ }>;
12
33
  export type PageFromDevice = Readonly<{
13
34
  id: string;
14
35
  title: string;
15
36
  vm: string;
16
37
  app: string;
17
- type?: "Legacy" | "Modern";
38
+ capabilities?: TargetCapabilityFlags;
18
39
  }>;
19
40
  export type Page = Required<PageFromDevice>;
20
41
  export type WrappedEvent = Readonly<{
@@ -55,7 +76,7 @@ export type PageDescription = Readonly<{
55
76
  vm: string;
56
77
  reactNative: Readonly<{
57
78
  logicalDeviceId: string;
58
- type: NonNullable<Page["type"]>;
79
+ capabilities: Page["capabilities"];
59
80
  }>;
60
81
  }>;
61
82
  export type JsonPagesListResponse = Array<PageDescription>;
@@ -63,38 +84,6 @@ export type JsonVersionResponse = Readonly<{
63
84
  Browser: string;
64
85
  "Protocol-Version": string;
65
86
  }>;
66
- /**
67
- * Types were exported from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts
68
- */
69
-
70
- export type SetBreakpointByUrlRequest = Readonly<{
71
- id: number;
72
- method: "Debugger.setBreakpointByUrl";
73
- params: Readonly<{
74
- lineNumber: number;
75
- url?: string;
76
- urlRegex?: string;
77
- scriptHash?: string;
78
- columnNumber?: number;
79
- condition?: string;
80
- }>;
81
- }>;
82
- export type GetScriptSourceRequest = Readonly<{
83
- id: number;
84
- method: "Debugger.getScriptSource";
85
- params: { scriptId: string };
86
- }>;
87
- export type GetScriptSourceResponse = Readonly<{
88
- scriptSource: string;
89
- /**
90
- * Wasm bytecode.
91
- */
92
- bytecode?: string;
93
- }>;
94
- export type ErrorResponse = Readonly<{ error: Readonly<{ message: string }> }>;
95
- export type DebuggerRequest =
96
- | SetBreakpointByUrlRequest
97
- | GetScriptSourceRequest;
98
87
  export type JSONSerializable =
99
88
  | boolean
100
89
  | number
@@ -9,6 +9,29 @@
9
9
  * @oncall react_native
10
10
  */
11
11
 
12
+ /**
13
+ * A capability flag disables a specific feature/hack in the InspectorProxy
14
+ * layer by indicating that the target supports one or more modern CDP features.
15
+ */
16
+ export type TargetCapabilityFlags = $ReadOnly<{
17
+ /**
18
+ * The target supports a stable page representation across reloads.
19
+ *
20
+ * In the proxy, this disables legacy page reload emulation and the
21
+ * additional '(Experimental)' target in `/json/list`.
22
+ *
23
+ * In the launch flow, this allows targets to be matched directly by `appId`.
24
+ */
25
+ nativePageReloads?: boolean,
26
+
27
+ /**
28
+ * The target supports fetching source code and source maps.
29
+ *
30
+ * In the proxy, this disables source fetching emulation and host rewrites.
31
+ */
32
+ nativeSourceCodeFetching?: boolean,
33
+ }>;
34
+
12
35
  // Page information received from the device. New page is created for
13
36
  // each new instance of VM and can appear when user reloads React Native
14
37
  // application.
@@ -18,7 +41,7 @@ export type PageFromDevice = $ReadOnly<{
18
41
  title: string,
19
42
  vm: string,
20
43
  app: string,
21
- type?: "Legacy" | "Modern",
44
+ capabilities?: TargetCapabilityFlags,
22
45
  }>;
23
46
 
24
47
  export type Page = Required<PageFromDevice>;
@@ -82,7 +105,7 @@ export type PageDescription = $ReadOnly<{
82
105
  // Metadata specific to React Native
83
106
  reactNative: $ReadOnly<{
84
107
  logicalDeviceId: string,
85
- type: $NonMaybeType<Page["type"]>,
108
+ capabilities: Page["capabilities"],
86
109
  }>,
87
110
  }>;
88
111
 
@@ -95,49 +118,6 @@ export type JsonVersionResponse = $ReadOnly<{
95
118
  "Protocol-Version": string,
96
119
  }>;
97
120
 
98
- /**
99
- * Types were exported from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts
100
- */
101
-
102
- export type SetBreakpointByUrlRequest = $ReadOnly<{
103
- id: number,
104
- method: "Debugger.setBreakpointByUrl",
105
- params: $ReadOnly<{
106
- lineNumber: number,
107
- url?: string,
108
- urlRegex?: string,
109
- scriptHash?: string,
110
- columnNumber?: number,
111
- condition?: string,
112
- }>,
113
- }>;
114
-
115
- export type GetScriptSourceRequest = $ReadOnly<{
116
- id: number,
117
- method: "Debugger.getScriptSource",
118
- params: {
119
- scriptId: string,
120
- },
121
- }>;
122
-
123
- export type GetScriptSourceResponse = $ReadOnly<{
124
- scriptSource: string,
125
- /**
126
- * Wasm bytecode.
127
- */
128
- bytecode?: string,
129
- }>;
130
-
131
- export type ErrorResponse = $ReadOnly<{
132
- error: $ReadOnly<{
133
- message: string,
134
- }>,
135
- }>;
136
-
137
- export type DebuggerRequest =
138
- | SetBreakpointByUrlRequest
139
- | GetScriptSourceRequest;
140
-
141
121
  export type JSONSerializable =
142
122
  | boolean
143
123
  | number
@@ -50,7 +50,7 @@ function openDebuggerMiddleware({
50
50
  // Only use targets with better reloading support
51
51
  (app) =>
52
52
  app.title === "React Native Experimental (Improved Chrome Reloads)" ||
53
- app.reactNative.type === "Modern"
53
+ app.reactNative.capabilities?.nativePageReloads === true
54
54
  );
55
55
  let target;
56
56
  const launchType = req.method === "POST" ? "launch" : "redirect";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native/dev-middleware",
3
- "version": "0.74.0-nightly-20240205-e4342f5b0",
3
+ "version": "0.74.0-nightly-20240206-bc3fe0d76",
4
4
  "description": "Dev server middleware for React Native",
5
5
  "keywords": [
6
6
  "react-native",
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@isaacs/ttlcache": "^1.4.1",
26
- "@react-native/debugger-frontend": "0.74.0-nightly-20240205-e4342f5b0",
26
+ "@react-native/debugger-frontend": "0.74.0-nightly-20240206-bc3fe0d76",
27
27
  "@rnx-kit/chromium-edge-launcher": "^1.0.0",
28
28
  "chrome-launcher": "^0.15.2",
29
29
  "connect": "^3.6.5",