Skip to content

Move /open-stack-frame into dev-middleware - #59316

Draft
huntie wants to merge 1 commit into
mainfrom
pr59316
Draft

huntie wants to merge 1 commit into
mainfrom
pr59316

Conversation

@huntie

@huntie huntie commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

/open-stack-frame, which LogBox and RedBox use to open a stack frame in the editor, is served only by @react-native-community/cli-server-api, so the dev server depends on the Community CLI for it. The CLI's copy also opens any path on disk and passes unchecked fields to the editor.

This diff moves the route into @react-native/dev-middleware, mounted when createDevMiddleware receives unstable_watchFolders, which runDevServer passes as the Metro server root and watchFolders. It ports Expo's hardening of its own copy (expo/expo#44039, expo/expo#45863).

  • Add optional launchEditor to DevToolLauncher. DefaultToolLauncher implements it with launch-editor and $REACT_EDITOR, matching the CLI.
  • Require a string file and keep lineNumber only when a positive integer; answer 400 otherwise.
  • Open only files whose real path is inside a watch folder, answering 400 otherwise. Checking every folder, not just the server root as Expo does, keeps frames from monorepo watchFolders opening.
  • Allow one launch every 2 seconds, answering 429 inside that window.
  • Refuse cross-origin browser requests with the inspector proxy's origin rule, now a shared helper. Native clients send no Origin and pass.
  • NOTE: Keep the CLI middleware mounted first, so its cross-origin guard still covers every core route. Core's handler skips a request an older CLI has already answered, so the editor opens once.

Paired with react-native-community/cli#2875, which removes the CLI's copy.

Changelog: [General][Added] - Dev server: @react-native/dev-middleware serves /open-stack-frame, restricted to the project watch folders

Test Plan

yarn jest packages/dev-middleware/src/__tests__/openStackFrameMiddleware-test.js

✅ Covers the launch with the posted file and line, same-origin and cross-origin requests, malformed bodies, containment (.., a symlink out, a nonexistent file, a watch folder itself), the throttle, launcher rejection, and a response an earlier middleware already sent.

RNTester on iPhone 18 Pro (iOS 27.0), with a throw added to the RNTesterApp render and $REACT_EDITOR set to a wrapper around VS Code's code that logs each launch. Tapped the top LogBox frame, RNTesterAppShared.js (95:18):

Community CLI Editor launches
Local cli-server-api with its /open-stack-frame removed, so core serves the route ✅ One: code -r -g …/rn-tester/js/RNTesterAppShared.js:95:1
npm cli-server-api 21.0.0-alpha.1, which mounts its own route first ✅ One, same arguments

With the local CLI, curl -X POST /open-stack-frame for a file in the repo answered 200 with core's OK body.

Not run: Flow; lint; iOS and Android RedBox.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 21, 2026

This branch has not been deployed

No deployments
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. p: Expo Partner: Expo Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant