Skip to content

Commit 01e228d

Browse files
divybotlittledivy
andauthored
fix: report eval scripts as [eval] URL for inspector (#34192)
## Summary Match Node.js by reporting `-e` and `deno eval` scripts as `[eval]` in inspector messages — `Debugger.scriptParsed`, `Debugger.paused` locations, and stack traces produced by `vm.runInThisContext`. Previously Deno reported the synthetic `file:///…/$deno$eval.mts` resource name (and `evalmachine.<anonymous>` for the user code inside the Node-compat wrapper), so any Node test that checks the script URL after attaching the inspector would fail. Two small changes: 1. **`eval_command`** appends `//# sourceURL=[eval]` to the eval source so V8 reports the eval main module URL as `[eval]`. Appended (not prepended) so user line numbers are preserved. 2. **`wrap_eval_code`** (used when Node-style `-e` is translated for child processes via `op_node_translate_cli_args`) passes `{ filename: "[eval]" }` to `vm.runInThisContext` so the wrapped user code is also reported with the `[eval]` URL. Enables `parallel/test-inspector-async-stack-traces-promise-then.js` in node compat. ## What's not in this PR The two timer tests referenced in the original issue (`test-inspector-async-stack-traces-set-interval.js` and `test-inspector-async-hook-setup-at-inspect-brk.js`) need pieces that don't exist yet and weren't appropriate to land here: - **`V8Inspector::asyncTaskScheduled` / `asyncTaskStarted` / `asyncTaskFinished` bindings.** Required so `setTimeout` / `setInterval` populate the `asyncStackTrace` field on `Debugger.paused`. V8 handles this automatically for promises via `SetAsyncEventDelegate`, but timers must call the hooks themselves. The `v8` crate doesn't expose these methods today — they need to be added in `denoland/rusty_v8` first. - **`node:internal/process/execution` frame on the async parent.** Both timer tests `.some()` over `asyncStackTrace.callFrames` looking for a frame with `frame.url === 'node:internal/process/execution'`. In Node this comes from `evalScript`, which lives in that internal module; Deno has no equivalent module today. - **`breakOnFirstLine` semantics.** `test-inspector-async-hook-setup-at-inspect-brk.js` expects the first `--inspect-brk` pause to be at line 1 of the user code, not at the wrapper's first statement. Node achieves this by passing `breakOnFirstLine` to `vm.Script::Compile`; V8 exposes the option but it's not on the Rust binding either. I left those tests commented out in `tests/node_compat/config.jsonc` for follow-up. ## Test plan - [x] `cargo test --test node_compat -- test-inspector-async-stack-traces-promise-then` → passes - [x] Confirm `[eval]` URL appears in `Debugger.scriptParsed` for both `deno eval` and spawn-translated `-e` paths - [x] `deno eval 'throw new Error()'` stack trace unchanged (V8 stack uses ScriptOrigin name, not sourceURL) - [x] `cargo test --test node_compat -- test-inspector-promises test-inspector-strip-types test-inspector-resource-name-to-url test-inspector-emit-protocol-event test-inspector-break-e test-inspector-multisession-ws` → no regression - [x] `cargo clippy --bin deno` Closes denoland/orchid#124 Co-authored-by: divybot <divybot@users.noreply.github.com> Co-authored-by: Divy Srivastava <me@littledivy.com>
1 parent 2270082 commit 01e228d

3 files changed

Lines changed: 7 additions & 2 deletions

File tree

cli/tools/run/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ pub async fn eval_command(
279279
} else {
280280
eval_flags.code
281281
};
282+
// Match Node's `[eval]` URL for `-e` scripts so inspector clients (and
283+
// Node compat tests) see the same script URL. V8 honors the
284+
// `//# sourceURL=` comment for both classic scripts and ES modules.
285+
// Appended (not prepended) so user line numbers are preserved.
286+
let source_code = format!("{source_code}\n//# sourceURL=[eval]\n");
282287

283288
// Save a fake file into file fetcher cache
284289
// to allow module access by TS compiler.

libs/node_shim/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3194,7 +3194,7 @@ pub fn wrap_eval_code(source_code: &str) -> String {
31943194
process.getBuiltinModule("module").builtinModules
31953195
.filter((m) => !/\/|crypto|process|_tls_common/.test(m))
31963196
.forEach((m) => {{ globalThis[m] = process.getBuiltinModule(m); }}),
3197-
process.getBuiltinModule("vm").runInThisContext({})
3197+
process.getBuiltinModule("vm").runInThisContext({}, {{ filename: "[eval]" }})
31983198
)"#,
31993199
json_escaped
32003200
)

tests/node_compat/config.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2280,7 +2280,7 @@
22802280

22812281
"parallel/test-inspector-esm.js": {},
22822282
"parallel/test-inspector-console.js": {},
2283-
// "parallel/test-inspector-async-stack-traces-promise-then.js": {},
2283+
"parallel/test-inspector-async-stack-traces-promise-then.js": {},
22842284
// "parallel/test-inspector-exception.js": {},
22852285
// "parallel/test-inspector-async-hook-setup-at-inspect-brk.js": {},
22862286
// "parallel/test-inspector-async-stack-traces-set-interval.js": {},

0 commit comments

Comments
 (0)