feat: inline sourcemaps for .ts modules and remap Error.stack to source#227
feat: inline sourcemaps for .ts modules and remap Error.stack to source#227benpalevsky wants to merge 2 commits into
Conversation
Compiles a Rust staticlib (transpiler-ffi/) built around SWC and exposed through a minimal two-function/one-struct C FFI, wired into the engine via SCsub. jsb_module_resolver loads .ts sources directly by transpiling them in-process into the CommonJS module wrapper, so TypeScript no longer needs a separate tsc emit step to run. Opt-in via a new use_typescript_transpiler build flag, off by default. With the flag off (the default) no Rust toolchain enters the build graph and every .ts code path is compiled out behind JSB_WITH_TYPESCRIPT_TRANSPILER: script loading keeps using the tsc-emitted .js (convert_typescript_path), the resolver does not probe .ts, and the build behaves as before this change. The FFI is panic-safe (catch_unwind at the boundary) and hands buffers to C through Box<[u8]> so the C-side free is sound. Build flags in SCsub allow the staticlib's libstd symbols to coexist with Godot's prebuilt accesskit staticlib on Linux/Windows.
The FFI now returns an inline data:application/json;base64 sourcemap URL, which the resolver appends to the wrapped module source as a //# sourceMappingURL comment and also decodes into a per-environment source-map cache. A V8 PrepareStackTraceCallback rewrites runtime Error.stack frames to .ts line/col through that cache, since V8 12.4 only applies source maps in DevTools and not to Error.stack.
|
I'll need to dig into this one. Source maps should already be working in general, but it's more in collaboration with the V8 debugger protocol. So like when you attach a debugger it can step through your original TS files on disk. By the look of it, this is more about logged stack traces? It's a good idea in general, but I wonder if I can get it working as an official external tool, rather than part of GodotJS builds. The ideal outcome would be that you're able to distribute your production builds without source maps, but you keep the build sourcemaps. Then when users report crashes, you could run them through a tool that gives you back clean .ts stack traces from real users. I'm not too keen on the embedded TS compiler, because SWC has limitations equivalent to |
Part 2 of 3 — the SWC stack. Builds on PR 5 (
5-swc-transpiler).Problem
When a
.tsfile is transpiled to JavaScript, the line and column numbers shift. So a runtime error points at a position in the generated JavaScript, not at your actual TypeScript source. That makes stack traces hard to read.What this adds
Real TypeScript stack traces.
.tsline Y").PrepareStackTraceCallback) rewrites each frame inError.stackback to its original.tsline and column, using a cache of those sourcemaps.The result: when something throws, the stack trace points at the
.tssource you actually wrote.Scope note (read before merging)
The
PrepareStackTraceCallbackhook is installed on every V8 build (#if JSB_WITH_V8), not just builds with the embedded transpiler. So this also routes the existingtscsourcemap path (and the defaultError.stackformatting) through the hook on a default build —Error.stackis now built by this callback and run through the sourcemap cache, where before it used V8's built-in formatter. That's a deliberate improvement to.jsstack traces, but it is a behavior change to the default build, and the frame regex is widened to also match.ts/.tsx/.mjs/.cjs. If maintainers prefer the default build untouched, the hook can instead be gated behind the transpiler flag (JSB_WITH_TYPESCRIPT_TRANSPILER) so only transpiler builds get it — happy to do that.Caveat to check
The remap matches each stack frame to the right sourcemap by source path. If the path V8 reports for a frame doesn't exactly match the key the sourcemap was stored under, that frame won't be remapped (it falls back to the generated position — no crash, just an unmapped frame). This is the one part that can only be confirmed by running it.
How to verify
Throw an error from inside a
.tsmodule and confirm the printed stack trace shows.tsfile positions, not generated.jspositions.A changeset is included. (Opened on its own, this PR's base is
5-swc-transpiler; see the README for how the stack is delivered.)