Skip to content

Fix source map symbolication in the presence of path collisions - #6432

Open
mstange wants to merge 3 commits into
firefox-devtools:mainfrom
mstange:push-oplxkpotnsvx
Open

mstange wants to merge 3 commits into
firefox-devtools:mainfrom
mstange:push-oplxkpotnsvx

Conversation

@mstange

@mstange mstange commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Main | Deploy preview

Fixes #6423.

Profile recorded with fixed version (requires deploy preview due to version bump): https://share.firefox.dev/4BvwYhP

This bumps the profile version to add the new column.

This addresses the case where two different JS bundles have an "original
source" with the same path in their source maps. E.g. both
`https://foo.com/bundle.js` and `https://bar.com/bundle.js` might contain
a source with the path `webpack://src/index.js`.

In theory, source map resolution could just create two separate sources
for the two original sources with the colliding paths, and not write down
in the profile which bundle they came from. That would work, but it would
not allow correct profile merging in the compare view; the merged profile
might accidentally merge sources that shouldn't be merged.

Remembering the bundle URL additionally lets us do the following (though
none of those things are attempted in this stack):
- For profiles where the source content has been sanitized out, we could
  have a feature in profiler-edit to put the source content back in.
- Relative path resolution: When displaying original sources with relative
  paths, we could display a resolved absolute path (resolved relative to
  the bundle) in the UI.
- We could display the bundle URL in any profiler-cli output that deals
  with sources.

For the upgrader, I considered making it so that it recovers the generated
source via funcTable / frameTable / sourceLocationTable, and splits sources
(+ makes corresponding source locations) for profiles where collisions
already happened, but it was too complicated. If we want the invariant that
sourceTable.generatedSource always matches funcTable.source, then we will
need to add this more complicated upgrader in a future version.
Fixes firefox-devtools#6423.

Original sources from source maps were identified by their URL alone.
Two bundles can list the same URL for different files, for example two
Speedometer suites that each bundle their own version of
../../node_modules/react-dom/cjs/react-dom-client.production.js.
Symbolication then treated them as one file: function names were looked
up in whichever file's content was seen first, and both bundles'
functions shared one source table row.

Now an original source is identified by the bundle whose source map
lists it, plus the URL as written in that source map. The worker
response carries a list of original sources, and resolutions refer to
entries by index. New source rows record their bundle in
generatedSource.

The apply step no longer tries to reuse any existing original sources
in the source table of the profile. Instead, it adds a row for an
original source when the first func or frame that refers to it is
applied.

If a bundler produced multiple "bundle chunks" which both include the
same original source, we will now have two different source table entries
for them. I think that's ok; I can't imagine this happens all that commonly.
Profile merging identified sources without an id by their filename. It
now identifies original sources from source maps by their bundle and
filename, like source map symbolication does.

Native symbolication looks up its file sources by filename among the
sources without an id. It now skips original sources from source maps,
since their URLs are only unique per bundle.
@mstange
mstange requested a review from canova October 29, 2026 20:46
@codecov

codecov Bot commented Oct 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.82759% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.81%. Comparing base (7269a79) to head (85a4d52).
⚠️ Report is 27 commits behind head on main.

Files with missing lines Patch % Lines
src/profile-logic/source-maps/symbolication.ts 92.30% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6432      +/-   ##
==========================================
+ Coverage   84.78%   84.81%   +0.02%     
==========================================
  Files         358      358              
  Lines       38946    38981      +35     
  Branches    10917    11041     +124     
==========================================
+ Hits        33022    33061      +39     
+ Misses       5488     5483       -5     
- Partials      436      437       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Collisions in source map symbolication

1 participant