Repository navigation
fix(javascript): catch the first call of a first-declared function breakpoint and explain a late entry stop (#858) - #863
Merged
Conversation
debugmcpdev
force-pushed
the
fix/858-js-entry-stop
branch
from
October 6, 2026 03:09
b7490aa to
f9283d4
Compare
…eakpoint and explain a late entry stop (#858) js-debug's stopOnEntry breakpoint sits at line 0 col 0 and V8 resolves it to the first breakable position in source order — the body of a function declared above the first statement — so the "entry" stop is that function's first call and recurs at every later call (microsoft/vscode-js-debug#2430). The forced entry stop that binds a pre-launch function breakpoint was that first call, auto-continued and lost. The CDP bridge now reports an entry stop whose paused frame is the function it just armed (matched by [[FunctionLocation]]) as the function breakpoint, and annotates an entry stop that landed inside a function in the stopped event's text; ChildSessionManager routes entry stops to the bridge with nothing armed. The adapter's inert --inspect-brk=9229 append and its --inspect promotion are removed (js-debug strips --inspect-brk into stopOnEntry itself). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
debugmcpdev
force-pushed
the
fix/858-js-entry-stop
branch
from
October 6, 2026 03:15
f9283d4 to
b459e5d
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #858. Builds on #862 (merged; shares the CDP bridge). Upstream: microsoft/vscode-js-debug#2430.
What was wrong
js-debug implements
stopOnEntryfor a Node launch withDebugger.setBreakpointByUrlat line 0, column 0 of the program. V8 resolves that position withFindClosestSharedFunctionInfoFromPosition— the nearest breakable position in source order across every function intersecting the span up to the first top-level statement — so for a file whose first declaration is a function the program calls later, the breakpoint lands in that function's body. Measured with a js-debug trace (adapterLaunchConfig.trace) on the issue's file B:breakpointResolvedat line 1 col 16 insidehelper, theentrystop 3 s later at the timer's call,startedalready printed. And since the breakpoint is never removed, every later call of the function stops asentryagain (file B with two calls: both stop).Two things followed on our side:
list_breakpointssayingverified: true.stopOnEntrylaunch stopped late, in the wrong place, with nothing saying so.Also found: the adapter's
--inspect-brk=9229append forstopOnEntrywas inert, and its promotion of a user's bare--inspectto--inspect-brk=9229forced an entry stop — js-debug strips--inspect-brkout ofruntimeArgsintostopOnEntryitself (resolveParamsin the vendored bundle). Node's own--inspect-brk(callAndPauseOnStart, pause on the first executed statement) is not reachable through js-debug's bootloader path;attachSimplePortwould give it but drops the bootloader, child-process debugging and the exit-code shim — rejected.What changes
src/proxy/cdp-function-breakpoint-bridge.ts): anentrystop whose paused frame'sfunctionLocationequals the[[FunctionLocation]]of a function armed at that stop is reported as that function breakpoint (reason: 'function breakpoint', its adapter id inhitBreakpointIds), so the SessionManager never auto-continues the first call. Matched by position, never by name. Anentrystop whose top frame is a named function — with or without function breakpoints — carries the explanation in the stopped event'stext: where it landed, why (line 1 col 1 + V8's source-order resolution), that the top-level code before the call has run, that every later call stops asentryagain, and what to do instead (a line breakpoint on the first statement). Thetexttravels withlastStopintostart_debugging,wait_for_stop,list_debug_sessionsandget_stack_trace. The entry-stop gate inChildSessionManagernow letsentrystops reach the bridge with nothing armed.--inspect-brk=9229append and the--inspect→--inspect-brkpromotion are gone; inspector flags pass through as given.docs/javascript/README.md,skills/debugging/references/javascript.md), changelog fragment, and the JavaScript: the entry stop lands inside the first-declared function when the program calls it — stopOnEntry stops late, and a function breakpoint on it skips its first call #858 thread carry the mechanism and the upstream link.Recorded, not built: a real fix — plant a hidden breakpoint on the first top-level statement (found with the vendored acorn) and swallow js-debug's own late
entry— noted in #858 as the follow-up.Verification
npm run typecheck:all(ratchet 0/0),npm run lint,node scripts/check-docs.mjs,pnpm changelog:check.[[FunctionLocation]]; no relabel for a same-named function at another location; late-entry note with nothing armed; top-level entry untouched),child-session-manager(entry stops routed with nothing armed, other reasons not), adapter transform (no inspector flags added or rewritten). Fullnpm run test:unitgreen.examples/javascript/function_first.js(function declared first, called 1.5 s in): a function breakpoint onworkstops at its first call withlate totalnot yet printed (previously ran to completion); astopOnEntrylaunch answerspaused/entrywithlastStop.textnamingwork(). Plus the fullmcp-server-smoke-js-function-bp,mcp-server-smoke-javascript,javascript-launch-configandmcp-server-logpointssuites.🤖 Generated with Claude Code