diff --git a/changelog.d/655.fixed.md b/changelog.d/655.fixed.md new file mode 100644 index 00000000..19b532cd --- /dev/null +++ b/changelog.d/655.fixed.md @@ -0,0 +1 @@ +**js `get_stack_trace` shows the user's frames, not the framework's** — on a js attach session paused inside an express/MCP server, `includeInternals: false` still returned ~60 frames: forty `node_modules/.pnpm/…` router/body-parser frames, ten phantom relative `../src/*.ts` paths (js-debug had applied every dependency's `.js.map`, whose sources are not shipped), and `` `await`/`Promise.then` separators. `JsDebugAdapterPolicy.isInternalFrame` matched only ``. It now also hides any `node_modules` path segment (pnpm and Windows layouts included) and sourceless line-0 async separators, and drops its local first-frame fallback so the central issue-#346 guarantee (`allFramesInternal` + note) finally engages for JS. On attach, `resolveSourceMapLocations` defaults to launch's `["**", "!**/node_modules/**"]` (js-debug's own attach default collapses to "resolve everywhere") so dependency frames report their real `.js` path, and `cwd` defaults to the server's working directory because js-debug resolves no relative map source without a base path — the debuggee's own `dist/**` maps now resolve to the absolute `src/**/*.ts` beside them instead of an unopenable `../src/…` label. Frames the adapter still cannot place on disk carry `unresolvedSource: true` and the response `note` says their `file` is a label, not a path. `skipFiles` is deliberately untouched on attach — blackboxing `node_modules` would re-open the #513 pause step-chase (#655) diff --git a/docs/agent-debugging-guide.md b/docs/agent-debugging-guide.md index 99b40f33..49920813 100644 --- a/docs/agent-debugging-guide.md +++ b/docs/agent-debugging-guide.md @@ -125,7 +125,7 @@ evaluate_expression(sessionId=session_id, expression="a + b") # Returns: "3" ## Common Issues and Solutions ### Issue: JavaScript shows Node.js internals in stack trace -**Solution:** Use `continue_execution` to move past internal frames. Stack trace filtering hides internal frames by default for supported languages. +**Solution:** Use `continue_execution` to move past internal frames. Stack trace filtering hides Node internals, `node_modules` dependency frames, and async separators by default; `includeInternals: true` shows them. A frame marked `unresolvedSource: true` is a source-map label, not a file you can open. ### Issue: Python shows "special variables" instead of actual variables **Solution:** This is normal hierarchical organization. Use the `variablesReference` to expand: @@ -446,7 +446,7 @@ capability, not a view-only credential. ## Summary The MCP Debugger is fully functional for Python, Ruby, JavaScript, Rust, Go, Java, .NET/C#, and C/C++. The key insights are: -- **JavaScript**: Stack trace filtering hides internal frames; may need `continue_execution` if initially stopped at internals +- **JavaScript**: Stack trace filtering hides internal, `node_modules`, and async-separator frames; may need `continue_execution` if initially stopped at internals - **Python**: Use variablesReference to expand variable containers - **Ruby**: Supports launch and attach flows through `rdbg`; use Bundler mode for Rails and RSpec-style entrypoints - **Rust**: CodeLLDB adapter is vendored; the GNU toolchain is required for reliable debugging -- MSVC-built binaries may produce errors with CodeLLDB. Set `RUST_MSVC_BEHAVIOR` env var to control MSVC handling diff --git a/docs/architecture/adapter-policy-pattern.md b/docs/architecture/adapter-policy-pattern.md index 8f80a420..ca8c9a10 100644 --- a/docs/architecture/adapter-policy-pattern.md +++ b/docs/architecture/adapter-policy-pattern.md @@ -237,7 +237,7 @@ whenever it is among the contributors. - `requiresCommandQueueing()` returns `true` -- commands are queued until initialize response, then reordered (configs -> configurationDone -> launch -> others) - Provides a full `performHandshake()` implementation for the js-debug multi-session setup - `isChildReadyEvent()` waits for `'thread'` or `'stopped'` (not `'initialized'`) -- `filterStackFrames()` removes `` frames +- `filterStackFrames()` removes ``/`node:` frames, any `node_modules` path segment, and sourceless line-0 async separators (issue #655); no local fallback — `FrameAnchorResolver` owns the all-internal case - `extractLocalVariables()` treats the local-like group as a COLLECTING group: every non-empty block scope (`Block`, `Catch Block`, `With Block`, legacy `Block: