feat(sourcemap): add wasm sourcemap support for inject and upload - #1588
d2anamaria wants to merge 1 commit into
Conversation
- Process wasm + map pairs alongside JS in inject and upload by default - Derive map debug IDs from the module build_id instead of content hash - Upload wasm and map as a matched artifact pair through existing API - Improve empty-directory errors when wasm modules lack companion maps
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
| const absDir = resolvePath(dir); | ||
| let wasmFiles = 0; | ||
| let wasmMaps = 0; | ||
| for await (const wasmPath of walkWasmModules(absDir)) { |
There was a problem hiding this comment.
Bug: The addWasmDiscoveryCounts function incorrectly counts ignored .wasm files, leading to a misleading error message about missing sourcemaps when files are intentionally excluded.
Severity: MEDIUM
Suggested Fix
Update the addWasmDiscoveryCounts function to accept an ignoreMatcher parameter. Pass this matcher to the walkWasmModules call to ensure it respects ignored files, consistent with discoverWasmPairs. The callers in upload.ts and inject.ts will also need to be updated to pass the matcher.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: packages/cli/src/lib/sourcemap/wasm.ts#L202
Potential issue: The `addWasmDiscoveryCounts` function does not respect ignore patterns
(from `.gitignore` or `--ignore`) because it fails to pass the `ignoreMatcher` to its
call to `walkWasmModules`. In contrast, the `discoverWasmPairs` function does pass the
matcher. This discrepancy causes incorrect diagnostics when all WebAssembly files in a
directory are ignored. The system will report that it found `.wasm` files but no
corresponding `.wasm.map` files, incorrectly advising the user to recompile with
`-gsource-map` when the actual issue is that the files are being ignored.
Did we get this right? 👍 / 👎 to inform future reviews.
| wasmFiles += 1; | ||
| if (await hasCompanionMap(`${wasmPath}.map`)) { | ||
| wasmMaps += 1; |
There was a problem hiding this comment.
Bug: Orphaned .wasm.map files are misclassified as JavaScript sourcemaps, resulting in a misleading error message that points to missing JS files instead of missing .wasm modules.
Severity: LOW
Suggested Fix
Adjust the diagnostic counting logic to correctly handle orphaned .wasm.map files. This could be done by ensuring .wasm.map files are not included in the initial JavaScript sourcemap count, or by modifying addWasmDiscoveryCounts to account for them properly, preventing them from being misreported.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: packages/cli/src/lib/sourcemap/wasm.ts#L203-L205
Potential issue: A logic flaw in diagnostic counting can produce a misleading error
message when a directory contains an orphaned `.wasm.map` file without a corresponding
`.wasm` file. The initial scan in `diagnoseEmptyDiscovery` counts all files ending in
`.map`, including the orphaned `.wasm.map`. However, the subsequent
`addWasmDiscoveryCounts` function only subtracts map counts for wasm maps that have a
companion `.wasm` file. As a result, the orphaned `.wasm.map` is incorrectly categorized
as a JavaScript sourcemap, leading to an error message stating "Found N .map file(s) ...
but no companion JS files."
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d27184b. Configure here.
| /** Whether a wasm pair was changed on disk. */ | ||
| function wasmChanged(result: WasmSyncResult): boolean { | ||
| return result.mapWritten || result.moduleStamped; | ||
| } |
There was a problem hiding this comment.
Dry-run marks wasm pairs unchanged
Medium Severity
--dry-run never sets mapWritten or moduleStamped, so wasmChanged stays false. Every wasm pair then counts as skipped and renders with a dash, even when the map would be stamped or the module would get a build_id. JavaScript pairs on the same dry-run still show as modified when they would change.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit d27184b. Configure here.


Problem
sentry sourcemap injectandsentry sourcemap uploadonly discover.js,.cjs, and.mjsfiles. Emscripten built with-gsource-mapemitsapp.wasmalongsideapp.wasm.map, a Source Map v3 JSON file. Discovery never sees the.wasm.map, so it is never uploaded.Even when a
.wasm.mapreaches Sentry by other means, nothing connects it to the module it describes. Sentry identifies a wasm module by thebuild_idcustom section, which events report asdebug_meta.images[].debug_id. Sourcemap uploads are matched by thedebug_idfield inside the map JSON. Those two identifiers were never tied together, so the map could not join its module.Adding
.wasmto the default extension set does not solve this. The JavaScript path mutates files as text: it reads them as UTF-8, prepends a runtime snippet, appends a//# debugId=comment, and offsets the map'smappingsto match. The first three corrupt a binary module, the fourth corrupts a map that has no lines to offset, and none of them is needed because a wasm module already carries its identity inbuild_id. Hashing file content for the debug ID, as the JS path does, would mint an identifier unrelated to the one events actually report.Solution
Both commands now process wasm pairs alongside JavaScript pairs. A directory with no wasm behaves exactly as before.
For each
app.wasm+app.wasm.mappair, the module'sbuild_idis the source of truth. It is the identifier the running module reports to Sentry. The CLI reads it, formats it as a canonical dashed UUID, and writes that value onto the map asdebug_idanddebugId. A module that has nobuild_idyet is stamped with a freshly generated random UUID first.The operation is idempotent. When the map already carries the matching id, neither file is touched, so re-running the command leaves the build output unchanged. When the map carries a different id, the module's id wins and the map is corrected — the map describes the module, not the other way round.
uploadsends the pair through the existing artifact-bundle path: the.wasmasminified_source, the.wasm.mapassource_map, both keyed by the same debug ID.--url-prefix,--strip-prefix,--strip-common-prefix,--release, and--distall apply.The module is never treated as text.
*.debug.wasmfiles are skipped. Those are DWARF companions belonging todebug-files prepare, uploaded through the debug-file pipeline instead.No new flags.
--dry-runreports the debug ID each pair would get and writes nothing.--no-rewritestamps nothing but still uploads under abuild_idalready on disk.--allow-emptycounts JS and wasm pairs together, so a wasm-only directory does not trip the "no .map files" error.--ignoreand--ignore-fileapply to wasm discovery.--extstays JavaScript-only; wasm discovery is fixed to.wasm.When a directory holds
.wasmfiles with no maps beside them, the empty-discovery error now points at-gsource-mapinstead of Vite and webpack settings. Command output lists reconciled wasm pairs alongside JS pairs.Limitations
Pair discovery
Pairing is by filename convention (
<stem>.wasm→<stem>.wasm.map). The module'ssourceMappingURLcustom section is not parsed, so a build that renames its map or writes it to another directory is skipped.Motivation: the section normally holds a deployment URL, set from Emscripten's
--source-map-base, which does not locate the file on disk. Resolving it correctly would also require classifying remote URLs and guarding against paths that escape the upload directory — work that yields nothing over the default layout.Inline sourcemaps
Inline (data-URL) wasm sourcemaps are not supported.
Motivation: no mainstream toolchain emits them. Supporting the form would require decoding the custom section, re-encoding the map, and rewriting the module's bytes, with no standalone file to upload.
Out of scope
build_idshorter than 16 bytes cannot form a UUID. Such a pair is left untouched rather than stamped with a malformed id.Notes for reviewers
Discovery now walks the target directory twice: once for JavaScript, once for
.wasm. The walks run sequentially, not concurrently. The added pass is cheap — it filters on extension, opens no files, and onlystats a candidate map, but it is a second traversal. Flagging it in case anyone wants it handled differently.sourcemap inject --jsonnow emits a"wasm"key listing the reconciled wasm pairs. It appears as an empty array for JavaScript-only directories, so the JSON shape changes slightly even when no wasm is involved. Nothing consumes the field today.This change aligns the identifiers so the uploaded artifacts are correct. It does not assume Symbolicator symbolicates wasm frames from source maps today.