Skip to content

React Native 0.87 debugger fixes and local build tooling - #2

Merged
teoboetti merged 6 commits into
masterfrom
fix/debugger-connection-and-first-run-breakpoints
Sep 28, 2026
Merged

teoboetti merged 6 commits into
masterfrom
fix/debugger-connection-and-first-run-breakpoints

Conversation

@teoboetti

Copy link
Copy Markdown
Owner

Everything needed to debug React Native 0.87 from Codium, plus the tooling to build and install it. This is the branch the local VSIX is built from.

Debugger fixes

Wait for the debug adapter server to bind before reading its port — Net.Server.listen() is asynchronous, so address() could still return null when DebugAdapterServer was constructed, pointing the session at an invalid port.

Set the expected Origin header when connecting to the Metro inspector — @react-native/dev-middleware validates Origin on /inspector/debug upgrades and answers 401 otherwise, so the CDP proxy never attached at all:

Connection from DevTools failed to be established for origin 'undefined'

Both of these mirror upstream PR microsoft#2782 by @urbanst, with two changes needed to actually compile here: import WebSocket = require("ws") instead of import * as (this repo has no esModuleInterop), and a cast at new WebSocketTransport(webSocket as any) because vscode-cdp-proxy resolves its own nested copy of @types/ws.

Reload the application once so first-run breakpoints are hit — the app finishes evaluating its bundle before the proxy attaches, so first-run breakpoints resolve but never fire. Hermes has no pause-on-load to wait for (Runtime.runIfWaitingForDebugger → -32601 Unsupported method), so HermesCDPMessageHandler sends a single Page.reload once the debugger goes quiet after its initial breakpoint requests. Covered by 5 unit tests.

Local-only commits

Not for upstream — drop before any PR to microsoft/vscode-react-native:

  • Resolve packages from the public npm registry — 220 lockfile tarballs pointed at internal Azure Artifacts feeds and registry.npmmirror.com, which npm rejects as remote packages (EALLOWREMOTE), so npm install failed outside Microsoft's network. Same mirrors, integrity hashes unchanged.
  • Bump version to 1.14.2 — keeps the sideloaded build ahead of the published 1.14.1 so Open VSX cannot replace it on auto-update.
  • VSIX build workflow and install-local script — packages on a v* tag and attaches the VSIX to the release; npm run install-local packages and installs into Codium in one step.

Validation

  • tsc --noEmit clean, gulp lint reports no new warnings
  • npm test — 465 passing, 0 failing (run npx gulp first, or commandsRegistered fails on a missing dist/rn-extension)
  • CI green on this branch, VSIX attached to v1.14.2
  • Verified end to end against React Native 0.87.1, iOS simulator, Hermes

Net.Server.listen() is asynchronous, so address() could still return null
when DebugAdapterServer was constructed, producing a debug session pointed
at an invalid port. Resolve the descriptor from the listen callback instead,
and surface bind failures through reject.
React Native's @react-native/dev-middleware validates the Origin header on
/inspector/debug WebSocket upgrades and closes connections whose origin is
neither the dev server nor a loopback host. The proxy connected without one,
so Metro answered 401 and logged:

  Connection from DevTools failed to be established for origin 'undefined'

Build the application transport explicitly so the Origin header derived from
the inspector URL is sent, and update the CDP proxy test for the new
transport creation path.
A launch installs and starts the app, which finishes evaluating its bundle
well before the CDP proxy manages to attach. Hermes replays scriptParsed on
Debugger.enable, so breakpoints registered for that first run resolve and
look bound, but the code they belong to has already executed and they are
never reached. Reloading by hand makes them work, which is what users hit
today.

Hermes has no pause-on-load to wait for: it answers
Runtime.runIfWaitingForDebugger with "Unsupported method" (-32601), so the
only lever is to run the bundle again once the debugger is ready. Send a
single Page.reload after the debugger goes quiet following its initial
breakpoint requests. Reloads are driven by the device (the nativePageReloads
capability), so the debugger stays attached and the breakpoints re-bind.

The request is sent out of band with an id the debugger never issued, so it
discards the reply as an unknown response id.
The lockfile pinned 220 tarballs to internal Azure Artifacts feeds and to
registry.npmmirror.com. npm refuses those as "remote" type packages
(EALLOWREMOTE), so npm install fails outside Microsoft's network. Both hosts
mirror the public registry at the same paths, so the integrity hashes are
unchanged.

Drop this commit before opening a pull request upstream.
Keeps the sideloaded build ahead of the published 1.14.1 so the marketplace
does not replace it on auto-update.

Drop this commit before opening a pull request upstream.
Packages the extension on a v* tag and attaches the VSIX to that release, so
it can be installed on a machine without the build toolchain. Also runnable
on demand via workflow_dispatch, which just uploads the artifact.

npm run install-local packages and installs into Codium in one step for the
local edit loop.

Drop this commit before opening a pull request upstream.
@teoboetti
teoboetti merged commit 7a27b7b into master Sep 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant