Skip to content

worker-build: emit Wasm source maps for emscripten builds - #1110

Open
JesusFileto wants to merge 1 commit into
cloudflare:mainfrom
JesusFileto:emscripten-source-maps
Open

JesusFileto wants to merge 1 commit into
cloudflare:mainfrom
JesusFileto:emscripten-source-maps

Conversation

@JesusFileto

Copy link
Copy Markdown
Contributor

Adds a source-map profile option for --emscripten builds. With debug = "line-tables-only", emcc links with -gsource-map, which builds a source map from the DWARF line tables before Binaryen optimizes and keeps the debug info out of the module, so it stays fully optimized. worker-build writes the map to build/index_bg.wasm.map and points the module's sourceMappingURL at it.

emcc names sources relative to the directory it wrote the map in, deep in cargo's target/, so once the map moves to build/ they point nowhere and still carry the build machine's home directory into uploaded maps. worker-build renames them as Cargo's still unstable trim-paths would: workspace sources relative to the workspace root, registry and git dependencies without $CARGO_HOME, and other paths absolute. This keeps names stable across machines and readable in stack traces, which is what they are used for, rather than paths relative to the map.

Like debug builds, source maps send DWARF through wasm-bindgen, so they need wasm-bindgen 0.2.129, the first release whose output Binaryen accepts. The Wasm binary helpers move from producers.rs to wasm_util.rs, since the source map code needs them too.

This can only be merged once worker-build's Emscripten pin moves to 6.0.14 or later, the first release with emscripten-core/emscripten#28033. Without it, code at DWARF line 0, such as an unreachable that LLVM shares between several branches, maps to the line before it instead of to no location.

Adds a `source-map` profile option for `--emscripten` builds. emcc
links with `-gsource-map` and builds the map from the DWARF line
tables of a `debug = "line-tables-only"` profile. The map is written
to `build/index_bg.wasm.map` with workspace-relative sources, and the
module's `sourceMappingURL` points to it. The Wasm binary helpers
move from producers.rs to wasm_util.rs so both can use them.
@logan-gatlin

logan-gatlin commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Nit: It seems like if you build once with source maps on, then build again with them off, the old source maps stay in the build folder. Unless the upload step later has some way of knowing that the build its uploading doesn't contain source maps, I think it would upload the stale source maps which wouldn't be good.


use anyhow::Result;

pub(crate) fn ensure_wasm_header(bytes: &[u8]) -> Result<()> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called in two places, both immediately follow the call let mut pos = 8 because they want to skip over the header. I know you didn't write this, just moved it, but it would be much nicer if this took a pos: &mut usize argument like the other functions in this file. That way the caller doesn't have to know how big the wasm header is. Another thing you could do is return a new slice inside the option, &bytes[8..], then the caller could do let bytes = ensure_wasm_header(bytes)?;.

const SOURCE_MAPPING_URL: &str = "sourceMappingURL";

/// The byte range of the custom section called `name`, if the module has one.
fn custom_section(wasm: &[u8], name: &str) -> Result<Option<(usize, usize)>> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could return std::ops::Range here

@logan-gatlin logan-gatlin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, marked do-not-merge while we wait on emscripten to update so we can bump the pin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants