…SOURCES Version 7 of the WebChannel renames the GET_JS_SOURCES request field from `sourceUuids` to `sourceIds`. The sender picks the field name based on the negotiated WebChannel version so both older Firefox (v6) and newer (v7+) builds are supported.
Lets the browser fetch source maps from URLs the frontend cannot reach. The frontend identifies the bundle source via its sourceId, and the browser returns the parsed source map. Currently it's plumbing only. No caller dispatches GET_SOURCE_MAP yet. Adds source-map and url as direct dependencies; `source-map` provides the RawSourceMap type and runtime parser, and `url` is required by source-map's URL resolution in browser bundles.
Extends the processed profile with a per-thread-shared SourceLocationTable (stored at profile.shared.originalLocation) and a content column on the SourceTable. Each frame and func now has a nullable originalLocation index, set to null by all existing initializers and upgraders. Source content stays null until JS symbolication populates it. The new tables are plumbed through data-structures, profile-compacting, merge-compare, and every importer. It adds a v63 upgrader and a CHANGELOG entry. No call site reads the new columns yet, behavior is unchanged.
The nonymous algorithm (johnjbarton.github.io/nonymous) is how SpiderMonkey labels anonymous JS functions inside its NameFunctions.cpp pass. Adds a parser and serializer for the `/`-separated, `<`-marked name format Gecko emits, so later symbolication can produce names that match what the browser already shows. Pure utility, no callers yet.
Parses compiled JS with @lezer/javascript and walks the CST to build a tree of function scopes with name-mapping locations. The character offsets later probed against the source map to recover original function names. `@lezer/javascript` is already a transitive dep via `@codemirror/lang-javascript`. Pure utility, no callers yet. Tested via the new source-map-scope-tree.test.ts.
Implements the off-main-thread part of JS source map symbolication. SourceMapStore wraps the source-map library's WASM-backed SourceMapConsumer, source-map-symbolication.ts walks every func and frame and maps its compiled position back to the original source via exact-match source-map lookups (with scope-tree probes to recover function names), and source-map.worker.ts wires those pieces up as a Web Worker entry point. The action thunk doSourceMapSymbolication spawns the worker on demand and dispatches BULK_SOURCE_MAP_SYMBOLICATION on success. No caller dispatches the thunk yet.
The Web Worker added in the previous patch needs its own bundle so the @lezer/javascript and source-map dependencies (plus the source-map WASM mappings) ship to the browser. Still no caller invokes the worker, so this patch only changes how `yarn build` builds the dist directory.
Activates JS source map symbolication end-to-end. After native symbolication settles, the receive-profile flow now fetches source maps and compiled JS for the bundle sources visible in any track, hands them to doSourceMapSymbolication, and lets the worker rewrite funcTable / frameTable / sourceMapInfo / sources / stringArray in-place via BULK_SOURCE_MAP_SYMBOLICATION. After this patch, sourceMapInfo is populated but UI code still reads the compiled positions. The next patch makes it look at sourceMapInfo.
The sourceMapInfo table is populated after the previous patch's wire-up, but no UI code read it yet. This patch teaches the source view, call tree, tooltip, line timings, and getOriginAnnotationForFunc to prefer source-mapped positions when present and fall back to the compiled position otherwise. Frame-level entries override func-level entries (so inlined code lands in the right original file). Adds the inline-content fallback in selectors/code.tsx: when the profile already carries sources.content (from a shared profile or from JS symbolication), the source view uses it directly instead of hitting the browser.
The source map pipeline (fetching + worker) previously ran invisibly after profile load. This surfaces two generic status messages in the existing SymbolicationStatusOverlay: "Fetching source maps..." while doResolveSourceMaps runs, and "Symbolicating JS source maps..." while the worker runs. Native symbolication takes priority. The source map messages only appear when the native overlay is not active. It's tracked via a new sourceMapSymbolicationStatus on viewOptions. Note that it looks like this component was never localized. We should do it! But I think this is a task for a follow-up
I noticed this bug while testing the source map PR locally. I was doing this: - Capture a profile with the JS sources feature enabled that includes source maps. - After the symbolication and source fetching, double click on a JS function that is source mapped. - Refresh the page. I was expecting it to work, but it was throwing errors because the source that I already opened wasn't in the profile and string table anymore (since it's added after the source map symbolication). So this fixes this issue by checking if the string table index is undefined
…debugging It proved somewhat difficult when I had the debug the source map symbolication worker on the worker thread. It makes things a lot easier when it runs on the main thread instead. I tried adding a const flag for this with its proper function, but esbuild wasn't properly removing the dead code, so it was inflating the bundle a lot when this function was there even if it was unused. I tried also converting that into an async import, which extracted the symbolication into a different bundle, but it was still outputting the extra bundle even if it was false constant value. So, I decided to include it as a commented out documentation in case we need it in the future. It's not the best, but it should still help us when we need to debug the worker in the future.
`fetchSourceAnnotation` was always reading from funcTable.source[funcIndex], which points at the compiled bundle. For JS-symbolicated functions the original file already lives behind funcTable.sourceMapInfo, and its text is typically embedded on the shared source table either by sourcesContent during symbolication or by the publish-with-sources path. Resolve the effective source through getOriginalPositionForFrame so the filename, line hit attribution, and content lookup all target the original source when sourceMapInfo is present. When sources.content is populated, use it directly and skip the network fetch entirely so the source view works offline for published-with-sources profiles.
…h native Refactor the source-map worker to return position-keyed resolutions instead of full table snapshots. The main thread applies the response against the current shared state via applySourceMapSymbolicationResponse, allocating sourceMapInfo rows, interning names, and deduping URLs against whatever native symbolication has committed by then. With per-funcIndex/per-frameIndex idempotency (skip rows already populated) and JS funcs/frames being insulated from native symbolication, the worker no longer needs to wait for native symbolication to finish. finalizeProfileView now runs source-map fetch, native symbolication, and the source-map worker all in parallel.
getStackLineInfo runs once per stack in the stack table, which can
mean hundreds of thousands of iterations on large profiles. Calling
getOriginalPositionForFrame in that loop allocated a fresh
{source, line, column} object per stack and always resolved the line
(and column) even though the line is only used when the stack's
source matches the source view, and the column is never used here.
Inline the 3-tier source-map fallback so we drop the per-stack
allocation, skip the column entirely, and defer the line lookup
until matchesSource is true. Apply the same inlining to
getTotalLineTimingsForCallNode, which has the same shape and only
needs the line.
Measured on a large profile: getStackLineInfo went from ~373ms back
to ~199ms.
Merged
canova added a commit that referenced this pull request
Jun 16, 2026Changes: [Nazım Can Altınova] Fix call node context menu being hidden behind source view bottom box (#6045) [Nazım Can Altınova] Pass `--use-env-proxy` only when the node version is >= 24 (#6064) [fatadel] Upgrade @firefox-devtools/react-contextmenu to 5.2.4 (#6066) [Markus Stange] Switch profiler-edit from minimist to commander (#6065) [Markus Stange] Support reading profiles from JsonSlabs files (#6037) [Florian Quèze] Don't fail profile processing when a marker's stack field is not a backtrace (#6069) [fatadel] Replace the footer-links overlay with a settings menu (#6042) [fatadel] Upgrade @types/node to match Node 24 (#6070) [fatadel] Remove unused undici-types package (#6074) [cathaysia] Update isLocalURL to include LAN addresses, .local domains, and hostn… (#5973) [Markus Stange] Fix from-url with binary profiles (#6072) [fatadel] Upgrade to React 19 (#6067) [Markus Stange] Add an insertStackLabels helper. (#6076) [fatadel] Drive counter tooltips from a tooltipRows schema (#6023) [fatadel] Add TrackPower--tooltip-average-power-microwatt (#6080) [Markus Stange] Downgrade to React 19.1 to fix unusable dev build performance. (#6082) [Nazım Can Altınova] Add source map symbolication and source view support (#6018) [spokodev] fix(FilterNavigatorBar): clip overflow so many breadcrumbs do not expand the parent (#6085) [Markus Stange] Move paddings inside the tree header cells. (#6002) [Markus Stange] Add an --insert-label-frames argument to the profiler-edit tool (#5966) [Markus Stange] Stop printing "error: too many arguments" during tests. (#6088) [Markus Stange] More additions to profiler-edit, for sp3 profiles (#6009) [Nazım Can Altınova] Do not rely on localized texts in the settings menu tests (#6101) And special thanks to our localizers: be: Andrei Mukamolau de: Ger de: Michael Köhler de: Ralf Duehnfahr el: Jim Spentzos en-CA: chutten en-GB: Ian Neal es-CL: ravmn fr: Théo Chevalier fr: wy fur: Fabio Tomat fy-NL: Fjoerfoks ia: Melo46 it: Francesco Lodolo [:flod] nl: Mark Heijl ru: Valery Ledovskoy sr: Марко Костић (Marko Kostić) sv-SE: Andreas Pettersson tr: Grk tr: Selim Şumlu zh-CN: Olvcpr423 zh-TW: Pin-guang Chen
canova added a commit to canova/perf.html that referenced this pull request
Jun 25, 2026…ation is requested This was a regression from firefox-devtools#6018. Previously, we didn't have a content column in the sources table. But we now added it, and they are filled automatically during the source map resolution. We would like to add a sharing feature soon, but this needs to be an explicit approval. Due to the early return in this `sanitizePII` function, we were mistakenly keeping these content values if we hit the early return (if the user wants to sanitize nothing). But even if the user wants to upload everything, we should unconditionally sanitize the sources.
Merged
canova added a commit that referenced this pull request
Jun 25, 2026…ation is requested (#6127) This was a regression from #6018. Previously, we didn't have a content column in the sources table. But we now added it, and they are filled automatically during the source map resolution. We would like to add a sharing feature soon, but this needs to be an explicit approval. Due to the early return in this `sanitizePII` function, we were mistakenly keeping these content values if we hit the early return (if the user wants to sanitize nothing). But even if the user wants to upload everything, we should unconditionally sanitize the sources.
This was referenced
Jul 17, 2026Closed
Closed