Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(dev-middleware): add custom message handlers to extend CDP capabilities #43291

Conversation

byCedric
Copy link
Contributor

@byCedric byCedric commented Mar 1, 2024

Summary:

This is a proposal for the @react-native/dev-middleware package, to allow implementers to extend the CDP capabilities of the InspectorProxy. It's unfortunately needed until we can move to the native Hermes CDP layer.

At Expo, we extend the CDP capabilities of this InspectorProxy by injecting functionality on the device level. This proposed API does the same, but without having to overwrite internal functions of both the InspectorProxy and InspectorDevice.

A good example of this is the network inspector's capabilities. This currently works through the inspection proxy, and roughly like:

  • Handle any incoming Expo(Network.receivedResponseBody) from the device, store it, and stop event from propagating
  • Handle the incoming Network.getResponseBody from the debugger, return the data, and stop event from propagating.

This API brings back that capability in a more structured way.

API:

import { createDevMiddleware } from '@react-native/dev-middleware';

const { middleware, websocketEndpoints } = createDevMiddleware({
  unstable_customInspectorMessageHandler: ({ page, deviceInfo, debuggerInfo }) => {
    // Do not enable handler for page other than "SOMETHING", or for vscode debugging
    // Can also include `page.capabilities` to determine if handler is required
    if (page.title !== 'SOMETHING' || debuggerInfo.userAgent?.includes('vscode')) {
      return null;
    }

    return {
      handleDeviceMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
      handleDebuggerMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
    };
  },
});

Changelog:

[GENERAL] [ADDED] - Add inspector proxy device message middleware API

Test Plan:

See added tests and code above

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner labels Mar 1, 2024
@byCedric byCedric force-pushed the @bycedric/dev-middleware/extendable-cdp-api branch from d95c558 to 49b0a79 Compare March 2, 2024 11:36
@byCedric byCedric marked this pull request as ready for review March 2, 2024 11:42
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Mar 2, 2024
@byCedric
Copy link
Contributor Author

byCedric commented Mar 4, 2024

Edit: this is now applied to this PR


One other change we could make in this API, is to move "instantiation of middleware" to whenever the debugger is connecting to the device/page.

By doing that, we limit the middleware instantiation to exactly the logical pairs we need to intercept. And, when the debugger disconnects, we can "destroy" the middleware and empty states.

The API itself would look somewhat like this:

const { middleware, websocketEndpoints } = createDevMiddleware({
  unstable_deviceMessageMiddleware: ({ page, deviceInfo, debuggerInfo }) => {
    // Do not enable middleware for page other than "SOMETHING", or for vscode debugging
    // Can also include `page.capabilities` to determine if middleware is required
    if (page.title !== 'SOMETHING' || debuggerInfo.userAgent.includes('vscode')) {
      return null;
    }

    return {
      handleDeviceMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something
          return true;
        }
      },
      handleDebuggerMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something
          return true;
        }
      },
    };
  },
});

@byCedric byCedric force-pushed the @bycedric/dev-middleware/extendable-cdp-api branch from a509df9 to 2085e46 Compare March 5, 2024 13:18
@byCedric byCedric force-pushed the @bycedric/dev-middleware/extendable-cdp-api branch from 2085e46 to 964a648 Compare March 5, 2024 13:18
Copy link
Contributor

@motiz88 motiz88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a massive step in the right direction, thank you @byCedric! I have some thoughts about the specifics of the design. (I might do another pass for nits/naming after the design is more settled.)


// The device message middleware instances, per debugger, page, and device connection
#messageMiddlewares: WeakMap<
DebuggerInfo,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using DebuggerInfo and Page as keys in a map seems brittle. Are there unique IDs we could use / generate for this purpose?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could we avoid WeakMap and structure our data differently to begin with, with proper cleanup when a connection is terminated etc?

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could nest the middleware instance under the debugger connection instead. That way, once that is cleared, the middleware should be garbage collected as well. I think a debugger connection always is to a single Page/device, so that should match the scope of the middleware too.

But I probably need some help related to Flow typing on that one, in the previous iteration I put it on the Page object but ran into exact/in-exact object typing issues here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ This is now nested inside the this.#debuggerConnection, and get's cleared once this connection is destroyed.

this.#getMessageMiddleware(
this.#debuggerConnection,
page,
)?.handleDeviceMessage(message);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Does handleDeviceMessage receive CDP messages or "inspector-proxy protocol" messages? It shouldn't be both.
  2. Doesn't handleDeviceMessage return a value we need to branch on?

This looks like it "wants" to just be a separate disconnected() method on the middleware.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment just above that on why the return value is not used here:

// NOTE(bycedric): Notify the device message middleware of the disconnect event, without any further actions.
// This can be used to clean up state in the device message middleware.

But, since we now scope the middleware on the actual device page and debugger connection, I don't think we need to do this anymore. The middleware should be fully garbage collected once either one disconnects. So we don't have to worry about disconnect events.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ This is now removed, as the whole custom message handler is garbage collected once this happens.

@@ -61,11 +62,11 @@ type Options = $ReadOnly<{
unstable_experiments?: ExperimentsConfig,

/**
* An interface for using a modified inspector proxy implementation.
* Create a middleware for handling unsupported CDP events, per device.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsupported CDP events

Pedantic nit: It looks like we actually give the middleware precedence over passing messages to/from the app, rather than just passing "unsupported" events to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per device

Per page, right?

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic nit: It looks like we actually give the middleware precedence over passing messages to/from the app, rather than just passing "unsupported" events to it.

Yes, unfortunately, we need to be able to influence "semi-supported" events too. It's mostly for vscode debugging, as some events are responded but not fully understood by vscode.js-debug. E.g. microsoft/vscode-js-debug#1583

There are more cases, or there could be more popping up. Having the ability to mutate or "replace"/workaround incompatible requests/responses would help us maintain the vscode debugging method. It's also the reason we implemented (and asked for) a debugger user agent, so we know if we need to enable more mutations etc.

Per page, right?

Your reaction is correct, I forgot to update this after the last iteration, will update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per page, right?

✅ I updated the docs

packages/dev-middleware/src/createDevMiddleware.js Outdated Show resolved Hide resolved
* It is instantiated per device and may contain state that is specific to that device.
* The middleware can also mark messages from the device or debugger as handled, which stops propagating.
*/
export interface DeviceMessageMiddleware {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does your use case not need the ability to also send notifications/events from the device to the debugger?

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, both ways. I kept the Device name as this happens on device level, just like we would do with the future native Hermes CDP API. But open to other names ofc 😄

For now, I'll apply your naming suggestion to everything, so that would be CustomMessageHandler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ This is now fully renamed to CustomMessageHandler

* This is invoked before the message is sent to the debugger.
* When returning true, the message is considered handled and will not be sent to the debugger.
*/
handleDeviceMessage(message: MessageFromDevice): true | void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think MessageFromDevice and MessageToDevice are the correct types here. Those represent the "inspector-proxy protocol", not CDP.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, my bad. It's a bit rough to find the right types here I think. Has to be generic as this library only types the supported events (while all events from both device and debugger are passing through these functions).

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ I don't think I used the right types, but since its a bit hard to strictly type this, I used the JSONSerializable type.

}>;

type ExposedDebuggerInfo = $ReadOnly<{
socket: $ElementType<DebuggerInfo, 'socket'>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't expose the raw socket to middleware. If the middleware needs the ability to send CDP messages, then CreateDeviceMessageMiddlewareFn should include a method to do that as a parameter.

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, in our implementation I added the sendToDebugger and sendToDevice methods anyways. I think we can move them to the debuggerInfo/deviceInfo, without exposing the socket directly.

e.g.

  • debuggerInfo.send = (message: DebuggerEvent | DebuggerMessage) => void
  • deviceInfo.send = (message: DeviceEvent | DeviceMessage) => void

Would that solve your point here? Not 100% sure yet about the typing, but you get the point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought about not allowing sending messages, and just return the message object from middleware (or null if it should stop propagating). But I think this would limit us too much in terms of supporting vscode.

Copy link
Contributor Author

@byCedric byCedric Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ I replaced the sockets with sendMessage methods.

Here are our custom handlers, and a quick check if this should work or not.

  • NetworkResponse
    This sends a response once Network.getResponseBody is requested from the debugger, should work fine.
  • PageReload
    Only replies with an acknowledge response to the debugger for Page.reload requests, should work fine.
  • VscodeDebuggerGetPossibleBreakpoints
    Replies to the unsupported Debugger.getPossibleBreakpoints request, with an empty locations list (as vscode does not check for nullablility / the locations: [] also required in the CDP spec).
  • VscodeDebuggerSetBreakpointByUrl
    Only mutates the message to avoid using unsupported way to set a breakpoint (through Debugger.setBreakpointByUrl)
  • VscodeRuntimeCallFunctionOn
    Replies to the debugger to avoid vscode injecting unsupported web scripts inside Hermes, which crashes Hermes / app.
  • VscodeRuntimeGetProperties
    Only mutates the message to avoid vscode performing actions on Symbols, which also crashes Hermes / app.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page.reload should check the nativePageReloads capability flags btw.

cc @dannysu for Hermes crashes, let's write Hermes unit tests / RN integration tests around them and see if they still occur in the new backend implementation

@byCedric byCedric force-pushed the @bycedric/dev-middleware/extendable-cdp-api branch from 2a3831f to d7a523f Compare March 6, 2024 13:00
@byCedric byCedric changed the title feature(dev-middleware): add proxy device middleware to extend CDP handling feature(dev-middleware): add custom message handlers to extend CDP capabilities Mar 7, 2024
Copy link
Contributor

@motiz88 motiz88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, see minor comments. In general could be worth rethinking some of the naming for clarity, but given that this is a short-term unstable API, I'm OK with shipping this.

@@ -411,6 +477,14 @@ export default class Device {
});
}

if (
this.#debuggerConnection?.customHandler?.handleDeviceMessage(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typically the thing to do is store the object in a local variable (const debuggerConnection = this.#debuggerConnection) and do the null checks on that. See https://flow.org/en/docs/lang/refinements/#toc-refinement-invalidations

appId: string,
id: string,
name: string,
sendMessage: (message: JSONSerializable) => void,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming nit: I don't think sendMessage() should be considered part of "info"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ It's now just connection.device.sendMessage and connection.debugger.sendMessage.

const payload = JSON.stringify(message);
debug('(Debugger) <- (Proxy) (Device): ' + payload);
socket.send(payload);
} catch {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why catch all exceptions here? Let's at minimum log them to debug()

Copy link
Contributor Author

@byCedric byCedric Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copied from the this.#sendMessageToDevice method:

// Sends single message to device.
#sendMessageToDevice(message: MessageToDevice) {
try {
if (message.event !== 'getPages') {
debug('(Debugger) (Proxy) -> (Device): ' + JSON.stringify(message));
}
this.#deviceSocket.send(JSON.stringify(message));
} catch (error) {}
}

Happy to add debugging logs for both though.

@@ -74,7 +78,10 @@ export default class Device {
#pages: $ReadOnlyMap<string, Page>;

// Stores information about currently connected debugger (if any).
#debuggerConnection: ?DebuggerInfo = null;
#debuggerConnection: ?{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's give this type a name (DebuggerConnection?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Added and implemented the type

@@ -499,7 +573,7 @@ export default class Device {
// Allows to make changes in incoming message from device.
async #processMessageFromDeviceLegacy(
payload: CDPServerMessage,
debuggerInfo: DebuggerInfo,
debuggerInfo: {...DebuggerInfo, ...},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we create the DebuggerConnection type, we can probably use it here directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can definitely do that; I was hesitant about doing so as this method only needs DebuggerInfo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Used DebuggerConnection instead

Copy link
Contributor Author

@byCedric byCedric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo

@facebook-github-bot
Copy link
Contributor

@motiz88 has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

facebook-github-bot pushed a commit that referenced this pull request Mar 12, 2024
…when header is unset (#43364)

Summary:
At Expo, we use [Expo Tools](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts) to connect the [built-in vscode-js-debug](https://github.com/microsoft/vscode-js-debug) to Hermes.

Since there are a few differences in vscode vs chrome devtools, we need to enable a couple of modifications through the [`customMessageHandler` API](#43291). Unfortunately, vscode itself doesn't set the `user-agent` header when connecting to the inspector proxy. Becuase of that, we'd need a fallback to "manually" mark the debugger as being vscode ([we use this query parameter here](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts#L208)).

This PR supports setting the `user-agent` through `?userAgent=` when the header is not set.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL] [ADDED] - Fallback to query parameter based `user-agent` when header is unset

Pull Request resolved: #43364

Test Plan:
- Install [Expo Tools](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools)
- Start Metro with this change.
- Connect a device.
- Run the vscode command `"Expo: Debug Expo app ..."`
- Debugger should connect, and have it's user-agent marked as:
    `vscode/1.87.0 vscode-expo-tools/1.3.0`

Reviewed By: huntie

Differential Revision: D54804556

Pulled By: motiz88

fbshipit-source-id: 1ff558ba5350811ad042d08a713438e046759feb
@github-actions github-actions bot added the Merged This PR has been merged. label Mar 12, 2024
Copy link

This pull request was successfully merged by @byCedric in 3f41fb5.

When will my fix make it into a release? | Upcoming Releases

huntie pushed a commit that referenced this pull request Mar 18, 2024
…when header is unset (#43364)

Summary:
At Expo, we use [Expo Tools](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts) to connect the [built-in vscode-js-debug](https://github.com/microsoft/vscode-js-debug) to Hermes.

Since there are a few differences in vscode vs chrome devtools, we need to enable a couple of modifications through the [`customMessageHandler` API](#43291). Unfortunately, vscode itself doesn't set the `user-agent` header when connecting to the inspector proxy. Becuase of that, we'd need a fallback to "manually" mark the debugger as being vscode ([we use this query parameter here](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts#L208)).

This PR supports setting the `user-agent` through `?userAgent=` when the header is not set.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL] [ADDED] - Fallback to query parameter based `user-agent` when header is unset

Pull Request resolved: #43364

Test Plan:
- Install [Expo Tools](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools)
- Start Metro with this change.
- Connect a device.
- Run the vscode command `"Expo: Debug Expo app ..."`
- Debugger should connect, and have it's user-agent marked as:
    `vscode/1.87.0 vscode-expo-tools/1.3.0`

Reviewed By: huntie

Differential Revision: D54804556

Pulled By: motiz88

fbshipit-source-id: 1ff558ba5350811ad042d08a713438e046759feb
huntie pushed a commit that referenced this pull request Mar 18, 2024
…pabilities (#43291)

Summary:
This is a proposal for the `react-native/dev-middleware` package, to allow implementers to extend the CDP capabilities of the `InspectorProxy`. It's unfortunately needed until we can move to the native Hermes CDP layer.

At Expo, we extend the CDP capabilities of this `InspectorProxy` by injecting functionality on the device level. This proposed API does the same, but without having to overwrite internal functions of both the `InspectorProxy` and `InspectorDevice`.

A good example of this is the network inspector's capabilities. This currently works through the inspection proxy, and roughly like:
- Handle any incoming `Expo(Network.receivedResponseBody)` from the _**device**_, store it, and stop event from propagating
- Handle the incoming `Network.getResponseBody` from the _**debugger**_, return the data, and stop event from propagating.

This API brings back that capability in a more structured way.

## API:

```ts
import { createDevMiddleware } from 'react-native/dev-middleware';

const { middleware, websocketEndpoints } = createDevMiddleware({
  unstable_customInspectorMessageHandler: ({ page, deviceInfo, debuggerInfo }) => {
    // Do not enable handler for page other than "SOMETHING", or for vscode debugging
    // Can also include `page.capabilities` to determine if handler is required
    if (page.title !== 'SOMETHING' || debuggerInfo.userAgent?.includes('vscode')) {
      return null;
    }

    return {
      handleDeviceMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
      handleDebuggerMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
    };
  },
});
```

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL] [ADDED] - Add inspector proxy device message middleware API

Pull Request resolved: #43291

Test Plan: See added tests and code above

Reviewed By: huntie

Differential Revision: D54804503

Pulled By: motiz88

fbshipit-source-id: ae918dcd5b7e76d3fb31db4c84717567ae60fa96
byCedric added a commit to expo/expo that referenced this pull request Mar 19, 2024
# Why

This is the implementation side of facebook/react-native#43291, and
facebook/react-native#43310.

~~PR is back in draft state due to
facebook/react-native#43559
Going to merge it as is, to fix CI.

# How

- Drop `InspectorProxy` and `Device` override classes
- Rename `InspectorHandlers` to `MessageMiddleware`
- ~~Temporarily polyfill required types until
`@react-native/dev-middleware` is published with this new API~~
_We now use all types from this package, derived from the
`CustomMessageHandlerConnection` and `CreateCustomMessageHandlerFn`
types._
- ~~Drop the `VscodeDebuggerScriptParsed` middleware as that mutates the
`Device` instance~~
_This was added to optimize the source map loading. It should still work
without this handler. There is work going on from Meta's side to make
source map loading follow web behavior more, but that's still in
progress._

# Test Plan

See updated tests, need to test this when `@react-native/dev-middleware`
is updated.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
This is required for changes to Expo modules.
-->

- [ ] Documentation is up to date to reflect these changes (eg:
https://docs.expo.dev and README.md).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
facebook-github-bot pushed a commit that referenced this pull request Mar 20, 2024
…#43559)

Summary:
This is a follow-up bugfix for expo/expo#27425, related to:
 - #43291
 - #43307
 - #43310
 - #43364

The middleware API works as intended and can run our extended CDP events. Unfortunately, this only applies to an actual `Page` from the device, not for the `React Native Experimental (Improved Chrome Reloads)` synthetic / virtual page.

That's because the middleware instantiation gets aborted when the page can't be found in `this.#pages.get(pageId)`, which always returns `null` for this synthetic page.

## Changelog:

[GENERAL] [FIXED] Create custom message handler for synthetic page

Pull Request resolved: #43559

Test Plan: See added test case.

Reviewed By: motiz88

Differential Revision: D55129412

Pulled By: huntie

fbshipit-source-id: 9679d8fe68f3cb4104f4a042f93612b995baddc9
huntie pushed a commit that referenced this pull request Mar 21, 2024
…#43559)

Summary:
This is a follow-up bugfix for expo/expo#27425, related to:
 - #43291
 - #43307
 - #43310
 - #43364

The middleware API works as intended and can run our extended CDP events. Unfortunately, this only applies to an actual `Page` from the device, not for the `React Native Experimental (Improved Chrome Reloads)` synthetic / virtual page.

That's because the middleware instantiation gets aborted when the page can't be found in `this.#pages.get(pageId)`, which always returns `null` for this synthetic page.

## Changelog:

[GENERAL] [FIXED] Create custom message handler for synthetic page

Pull Request resolved: #43559

Test Plan: See added test case.

Reviewed By: motiz88

Differential Revision: D55129412

Pulled By: huntie

fbshipit-source-id: 9679d8fe68f3cb4104f4a042f93612b995baddc9
This was referenced Jun 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants