Deploy June 16, 2026#6103
Merged
Merged
Conversation
We'll want to add a binary serialization soon, but we'll also keep the JSON serializatios as an option. This rename makes it clear which one you're calling.
Fixes #6024. JsonSlabs is an alternative serialization format that's more efficient than JSON if the serialized object contains typed arrays. See https://github.com/mstange/json-slabs/ for details. Our profiles currently do not yet contain typed arrays. But with this in place, we can start converting more and more tables / columns to use typed arrays, and incrementally reap the efficiency benefits. This patch only adds the reading. In the UI, uploading / downloading profiles still uses JSON. For the profiler-edit node script, this patch also adds the "writing": If you run profiler-edit with `-o some-filename-ending-in.jslb`, then it will create a JSLB file (or a compressed JSLB file for .jslb.gz). --- The profile format "structure" is still the same as before. The format version is still given by profile.meta.preprocessedProfileVersion. Loading a JSLB file with a profile.meta.preprocessedProfileVersion that's higher than the currently known one will still complain, and attempt to reload the page or the service worker. This reload behavior is the primary reason why I want to get the "reading" part taken care of first, before we start converting any parts of the profile to get efficiency wins: The sooner we land this, the more likely it will be that, in the future, if somebody has a newer JSLB file but an old cached profiler, they'll see a useful error and get the auto-reload. Without this patch, loading a JSLB file in the profiler gives the following error: > Error: Unserializing the profile failed: Error: The profile array > buffer could not be parsed as a UTF-8 string. --- With all that said, it turns out there is already a case where this format gives an efficiency win, thanks to its "split out" feature that lets us put certain subtrees of the profile into separate JSON slabs: If the original JSON is larger 512MiB, we can split it into individual slabs which are each smaller than 512MiB, so the built-in JSON.parse will work and we don't have to use the slow streaming parse. Example: https://storage.googleapis.com/profiler-get-symbols-fixtures/large-speedometer3-profile.json.gz expands to a 577.74MB JSON file, https://storage.googleapis.com/profiler-get-symbols-fixtures/large-speedometer3-profile.jslb.gz expands to a 564.66MB JSLB file (slightly smaller because compacting removed unused strings) The JSLB file breaks down as follows: ``` idx type bytes elements path --- ------- ---------- -------- ------------------- 0 json 16.76 MiB - . (root) 1 json 264.82 MiB - .shared.stackTable 2 json 91.01 MiB - .shared.frameTable 3 json 8.47 MiB - .shared.funcTable 4 json 28.80 MiB - .shared.stringArray 5 json 154.80 MiB - .threads --- ------- ---------- -------- ------------------- 6 slabs 564.66 MiB ``` All of those individual JSON slabs are now under 512MiB. Loading the JSON file, uses streaming parser: https://share.firefox.dev/3PcB9vK (19 seconds) Loading the JSLB file, uses native JSON.parse: https://share.firefox.dev/3RkFcXs (2.3 seconds, 8.3x faster)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
…#6045) DetailsContainer set `position: relative; z-index: 0`, creating a stacking context that trapped the context menus (rendered inside DetailsContainer) at z-index 0. The BottomBox is a sibling of DetailsContainer that comes later in the DOM, so it painted on top of the menus whenever the source view was open. Removing the stacking context from DetailsContainer lets the context menu's --z-context-menu compete at .profileViewer level and paint above the BottomBox. The parent .profileViewer still provides a stacking context for the KeyboardShortcut overlay.
The flag was added in Node 24. On older runtimes node exits immediately with "bad option" before the daemon can write any log, create the session directory, or bind its socket. The client process has no visibility into the spawned daemon (stdio is ignored and no exit listener is attached), so the user only sees "Failed to start daemon: session not validated after 500ms" with no indication that the daemon crashed on startup. Pass the flag conditionally based on process.versions.node, and warn on stderr when a proxy env var is set but the runtime is too old to honor it.
startNewDaemon previously spawned the daemon with stdio: 'ignore' and no exit listener, so any spawn-time failure (unsupported Node flag, missing dependency, immediate crash) surfaced only as a generic "session not validated after 500ms" timeout. The user had no way to tell whether the daemon was slow to start or had died on launch. Attach 'exit' and 'error' listeners to the spawned child and check them on every phase 1 polling iteration (and once after the loop, in case the daemon exits while a final validation is in flight). When the daemon dies early, throw an error that includes the exit code or signal and points the user at the session log directory.
See also individual commit messages. `--use-env-proxy` was added in Node.js 24, and I added that in #6003 to make sandboxed anvironments work. But the cli now stopped working for the users who has node version that's below 24. This PR adds this flag conditionally if the node version is above that. Note that sandboxed environments might not work for node < 24. But I added a warning log to the users explaining that.
Co-authored-by: Selim Şumlu <selim@sum.lu> (tr)
[Deploy preview](https://deploy-preview-6037--perf-html.netlify.app/) (load [this example jslb](https://storage.googleapis.com/profiler-get-symbols-fixtures/normal-profile.jslb.gz) in it) Fixes #6024. JsonSlabs is an alternative serialization format that's more efficient than JSON if the serialized object contains typed arrays. See https://github.com/mstange/json-slabs/ for details. Our profiles currently do not yet contain typed arrays. But with this in place, we can start converting more and more tables / columns to use typed arrays, and incrementally reap the efficiency benefits. This patch only adds the reading. In the UI, uploading / downloading profiles still uses JSON. For the profiler-edit node script, this patch also adds the "writing": If you run profiler-edit with `-o some-filename-ending-in.jslb`, then it will create a JSLB file (or a compressed JSLB file for .jslb.gz). --- The profile format "structure" is still the same as before. The format version is still given by profile.meta.preprocessedProfileVersion. Loading a JSLB file with a profile.meta.preprocessedProfileVersion that's higher than the currently known one will still complain, and attempt to reload the page or the service worker. This reload behavior is the primary reason why I want to get the "reading" part taken care of first, before we start converting any parts of the profile to get efficiency wins: The sooner we land this, the more likely it will be that, in the future, if somebody has a newer JSLB file but an old cached profiler, they'll see a useful error and get the auto-reload. Without this patch, loading a JSLB file in the profiler gives the following error: > Error: Unserializing the profile failed: Error: The profile array > buffer could not be parsed as a UTF-8 string. --- With all that said, it turns out there is already a case where this format gives an efficiency win, thanks to its "split out" feature that lets us put certain subtrees of the profile into separate JSON slabs: If the original JSON is larger 512MiB, we can split it into individual slabs which are each smaller than 512MiB, so the built-in JSON.parse will work and we don't have to use the slow streaming parse. Example: https://storage.googleapis.com/profiler-get-symbols-fixtures/large-speedometer3-profile.json.gz expands to a 577.74MiB JSON file, https://storage.googleapis.com/profiler-get-symbols-fixtures/large-speedometer3-profile.jslb.gz expands to a 564.66MiB JSLB file (slightly smaller because compacting removed unused strings) The JSLB file breaks down as follows: ``` idx type bytes elements path --- ------- ---------- -------- ------------------- 0 json 16.76 MiB - . (root) 1 json 264.82 MiB - .shared.stackTable 2 json 91.01 MiB - .shared.frameTable 3 json 8.47 MiB - .shared.funcTable 4 json 28.80 MiB - .shared.stringArray 5 json 154.80 MiB - .threads --- ------- ---------- -------- ------------------- 6 slabs 564.66 MiB ``` All of those individual JSON slabs are now under 512MiB. Loading the JSON file, uses streaming parser: https://share.firefox.dev/3PcB9vK (19 seconds) Loading the JSLB file, uses native JSON.parse: https://share.firefox.dev/3RkFcXs (2.3 seconds, 8.3x faster) --- The example jslb next to the deploy preview link was generated as follows: `yarn build-node-tools && node ./node-tools-dist/profiler-edit.js --from-hash 29apty4565r8dec0hrjfty68w88rexc6na6bn1r -o ~/Downloads/normal-profile.jslb.gz` --- Follow-ups: - Land Rust tools in the json-slabs repo to list .jslb contents / convert to JSON / expand to directory (I have most of this written already) - Allow uploading jslb files to profile storage - Add UI to the sharing panel to allow downloading as either json or jslb - Actually start migrating tables / columns to typed arrays - Change uploading to use jslb instead of json - Update samply / fxprof-processed-profile to support outputting to jslb
…cktrace The marker payload stack key normally holds a captured backtrace (a mini thread with a samples table), which we convert into a cause. But the key isn't reserved: some markers store an unrelated value there, e.g. Log markers emitted by the test harness put a textual JS stack trace string in it. Processing such a marker threw (accessing .samples.data on a string), making the whole profile fail to load. Check that the stack value actually has a samples table before treating it as a backtrace. A non-backtrace stack is now left untouched on the payload, to be displayed (or ignored) by the marker schema like any other field.
…cktrace (#6069) The marker payload stack key normally holds a captured backtrace (a mini thread with a samples table), which we convert into a cause. But the key isn't reserved: some markers store an unrelated value there, e.g. Log markers emitted by the test harness put a textual JS stack trace string in it. Processing such a marker threw (accessing .samples.data on a string), making the whole profile fail to load. Check that the stack value actually has a samples table before treating it as a backtrace. A non-backtrace stack is now left untouched on the payload, to be displayed (or ignored) by the marker schema like any other field. Example profile that fails to load without this fix: https://share.firefox.dev/49tsCeI
The footer-links overlay was a small floating box pinned to the bottom-right corner of every page that often obstructed the UI underneath, and the app's settings/links were scattered across the overlay and the top bar. Consolidate the overlay's contents (Legal, Privacy, Cookies, language switcher) together with the Docs link and the theme toggle into a single settings menu opened from a cog icon, so all app-wide controls live in one place. The cog is available on every page — home, compare, uploaded recordings, and while viewing a profile.
Co-authored-by: Ian Neal <iann_bugzilla@blueyonder.co.uk> (en-GB)
Co-authored-by: Michael Köhler <michael.koehler1@gmx.de> (de) Co-authored-by: Andrei Mukamolau <skiinale2011@gmail.com> (be)
Co-authored-by: Francesco Lodolo [:flod] <flod+pontoon@mozilla.com> (it)
Co-authored-by: Valery Ledovskoy <valery@ledovskoy.com> (ru)
Co-authored-by: Andreas Pettersson <amvpet@gmail.com> (sv-SE)
Co-authored-by: Fjoerfoks <fryskefirefox@gmail.com> (fy-NL, nl)
Co-authored-by: Pin-guang Chen <petercpg@mail.moztw.org> (zh-TW)
Co-authored-by: ravmn <ravmn@ravmn.cl> (es-CL)
Co-authored-by: Марко Костић (Marko Kostić) <marko.m.kostic@gmail.com> (sr)
Co-authored-by: Théo Chevalier <theo@theochevalier.org> (fr) Co-authored-by: wy <awatt@gmx.com> (fr)
Co-authored-by: chutten <chutten@mozilla.com> (en-CA)
Co-authored-by: chutten <chutten@mozilla.com> (en-CA)
Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.1 to 1.8.4. - [Changelog](https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md) - [Commits](ljharb/shell-quote@v1.8.1...v1.8.4) --- updated-dependencies: - dependency-name: shell-quote dependency-version: 1.8.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.1 to 1.8.4. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md">shell-quote's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/ljharb/shell-quote/compare/v1.8.3...v1.8.4">v1.8.4</a> - 2026-05-22</h2> <h3>Commits</h3> <ul> <li>[Fix] <code>quote</code>: validate object-token shapes <a href="https://github.com/ljharb/shell-quote/commit/4378a6e613db5948168684864e49b42b83134d2d"><code>4378a6e</code></a></li> <li>[Dev Deps] update <code>@ljharb/eslint-config</code>, <code>auto-changelog</code>, <code>eslint</code>, <code>npmignore</code> <a href="https://github.com/ljharb/shell-quote/commit/22ebec04349065a45ad8afc8cc8d53c4624634a6"><code>22ebec0</code></a></li> <li>[Tests] increase coverage <a href="https://github.com/ljharb/shell-quote/commit/9f3caa31900cc6ee64858b31134144c648ce206d"><code>9f3caa3</code></a></li> <li>[readme] replace runkit CI badge with shields.io check-runs badge <a href="https://github.com/ljharb/shell-quote/commit/3344a047dd1e95f71c4ca27522cbfd05c56277e0"><code>3344a04</code></a></li> <li>[Dev Deps] update <code>@ljharb/eslint-config</code> <a href="https://github.com/ljharb/shell-quote/commit/699c5113d135f4d4591574bebf173334ffa453d4"><code>699c511</code></a></li> </ul> <h2><a href="https://github.com/ljharb/shell-quote/compare/v1.8.2...v1.8.3">v1.8.3</a> - 2025-06-01</h2> <h3>Fixed</h3> <ul> <li>[Fix] remove unnecessary backslash escaping in single quotes <a href="https://redirect.github.com/ljharb/shell-quote/issues/15"><code>[#15](https://github.com/ljharb/shell-quote/issues/15)</code></a></li> </ul> <h2><a href="https://github.com/ljharb/shell-quote/compare/v1.8.1...v1.8.2">v1.8.2</a> - 2024-11-27</h2> <h3>Fixed</h3> <ul> <li>[Fix] <code>quote</code>: preserve empty strings <a href="https://redirect.github.com/ljharb/shell-quote/issues/18"><code>[#18](https://github.com/ljharb/shell-quote/issues/18)</code></a></li> </ul> <h3>Commits</h3> <ul> <li>[meta] fix changelog tags <a href="https://github.com/ljharb/shell-quote/commit/0fb9fd8441aa06f7de995e90ce85bd9e758f5f05"><code>0fb9fd8</code></a></li> <li>[actions] split out node 10-20, and 20+ <a href="https://github.com/ljharb/shell-quote/commit/819bd842e0b01f3e5041834ab82bad299851de08"><code>819bd84</code></a></li> <li>[Dev Deps] update <code>@ljharb/eslint-config</code>, <code>auto-changelog</code>, <code>npmignore</code>, <code>tape</code> <a href="https://github.com/ljharb/shell-quote/commit/fc564086c83317363908b55f6c744ad35983ccca"><code>fc56408</code></a></li> <li>[actions] update npm for windows tests <a href="https://github.com/ljharb/shell-quote/commit/fdeb0fd102ecdd4ff227a978532598c462312347"><code>fdeb0fd</code></a></li> <li>[Dev Deps] update <code>@ljharb/eslint-config</code>, <code>aud</code>, <code>tape</code> <a href="https://github.com/ljharb/shell-quote/commit/b8a4a3b3f5ae3ca8ae86b89ed0030e4e3358ef3c"><code>b8a4a3b</code></a></li> <li>[actions] prevent node 14 on ARM mac from failing <a href="https://github.com/ljharb/shell-quote/commit/9eecafc0486c9321be223415cf3fb76a5bd07dda"><code>9eecafc</code></a></li> <li>[meta] exclude more files from the package <a href="https://github.com/ljharb/shell-quote/commit/4044e7fad4a45e696602060b69b31a95702bee28"><code>4044e7f</code></a></li> <li>[Tests] replace <code>aud</code> with <code>npm audit</code> <a href="https://github.com/ljharb/shell-quote/commit/8cfdbd8ec30e653f9f99348e59117ed4a789e1ba"><code>8cfdbd8</code></a></li> <li>[meta] add missing <code>engines.node</code> <a href="https://github.com/ljharb/shell-quote/commit/843820e1a46cebcf10d8e48c4d82d0ab5a7b0194"><code>843820e</code></a></li> <li>[Dev Deps] add missing peer dep <a href="https://github.com/ljharb/shell-quote/commit/4c3b88d7925d29e9cc1ac76ccde05f4e714ede96"><code>4c3b88d</code></a></li> <li>[Dev Deps] pin <code>jackspeak</code> since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6 <a href="https://github.com/ljharb/shell-quote/commit/80322ed5914a5922d9507946490fbabcc96e624b"><code>80322ed</code></a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/ljharb/shell-quote/commit/ff166e2b63eb5f932bd131a8886a99e9afdf45ae"><code>ff166e2</code></a> v1.8.4</li> <li><a href="https://github.com/ljharb/shell-quote/commit/4378a6e613db5948168684864e49b42b83134d2d"><code>4378a6e</code></a> [Fix] <code>quote</code>: validate object-token shapes</li> <li><a href="https://github.com/ljharb/shell-quote/commit/22ebec04349065a45ad8afc8cc8d53c4624634a6"><code>22ebec0</code></a> [Dev Deps] update <code>@ljharb/eslint-config</code>, <code>auto-changelog</code>, <code>eslint</code>, `npmig...</li> <li><a href="https://github.com/ljharb/shell-quote/commit/9f3caa31900cc6ee64858b31134144c648ce206d"><code>9f3caa3</code></a> [Tests] increase coverage</li> <li><a href="https://github.com/ljharb/shell-quote/commit/3344a047dd1e95f71c4ca27522cbfd05c56277e0"><code>3344a04</code></a> [readme] replace runkit CI badge with shields.io check-runs badge</li> <li><a href="https://github.com/ljharb/shell-quote/commit/699c5113d135f4d4591574bebf173334ffa453d4"><code>699c511</code></a> [Dev Deps] update <code>@ljharb/eslint-config</code></li> <li><a href="https://github.com/ljharb/shell-quote/commit/487a9b41a7b6154d2a9c10bdffe65cf74d2c3ded"><code>487a9b4</code></a> v1.8.3</li> <li><a href="https://github.com/ljharb/shell-quote/commit/01faafff9727bf2b72ede0e7cb291bdd8438a8df"><code>01faaff</code></a> [Fix] remove unnecessary backslash escaping in single quotes</li> <li><a href="https://github.com/ljharb/shell-quote/commit/b19fc77e66871eee10a9978d54c27d802a1da99b"><code>b19fc77</code></a> v1.8.2</li> <li><a href="https://github.com/ljharb/shell-quote/commit/59d29ea6941335258ceb75bab95d045886650436"><code>59d29ea</code></a> [Fix] <code>quote</code>: preserve empty strings</li> <li>Additional commits viewable in <a href="https://github.com/ljharb/shell-quote/compare/v1.8.1...v1.8.4">compare view</a></li> </ul> </details> <br />
Fixes #6079. Co-authored-by: Nazım Can Altınova <canaltinova@gmail.com>
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Commander 15 is ESM only, so we need to add it to this list to make sure it is transformed into CommonJS for Jest.
This makes it so that you can run profiler-edit with `--insert-label-frames browser_labels.toml --only-keep-threads-with-markers-matching='-async,-sync' --merge-non-overlapping-threads-by-name --set-name 'Sp3 5x (with labels, combined main threads)'` to turn https://share.firefox.dev/4cXQFED into https://share.firefox.dev/4ezEcsa
`openMenu` is added recently since we moved the locale picker to inside the cog menu. And `openMenu` was checking for an English text to find the settings button. But also some subtests in this file are changing the locales for testing. This commit changes that so we don't use any localized texts in there to make sure that it works even if the localizations are updated.
Updated locales: be, de, el, en-CA, en-GB, es-CL, fr, fur, fy-NL, ia, it, kab, nl, pt-BR, ru, sr, sv-SE, tr, uk, zh-CN, zh-TW.
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> Co-authored-by: Nazım Can Altınova <canaltinova@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes:
[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-proxyonly 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